Wykład 10: Wejście i Wyjście
Transkrypt
Wykład 10: Wejście i Wyjście
Wykład 10: Wejście i Wyjście Wejście/Wyjście Program realizuje wejście/wyjście przez użycie potoku. Ten sam sposób obsługi różnych urządzeń: konsola ● klawiatura ● plik na dysku ● gniazdko sieciowe, itp. ● Program nie musi znać różnicy między obsługą np. czytania z klawiatury, czy obsługą czytania z sieci. Pakiet java.io. Potoki Dwa rodzaje: ● ● bajtowy – pisanie/czytanie danych binarnych znakowy – pisanie/czytanie danych znakowych: ● używa Unicode (internacjonalizacja) ● bardziej efektywny ● implementacja bajtowa Potoki Bajtowe Klasy abstrakcyjne InputStream i OutputStream Abstrakcyjne metody read() i write(). Pod-klasy: ● ● ● ● ● ● ● ● ● ● Buffered... buforowany I/O ByteArray... I/O z tablicy bajtów Data... I/O ze standardowych typów danych File... I/O z plików Filter... implementuje ...Stream Piped... łączenie potoków PrintStream OutputStream z print() i println() PushbackInputStream InputStream z "unget" RandomAccessFile losowy dostęp do pliku SequenceInputStream sekwencja liczby potoków Potoki Znakowe Klasy abstrakcyjne Reader i Writer. Abstrakcyjne metody read() i write(). Pod-klasy: ● ● ● ● ● ● ● ● ● ● Buffered... buforowany I/O CharArray... I/O z tablicy znaków File... I/O z plików Filter... I/O z filtrowaniem String... I/O z ciągu znaków Piped... łączenie potoków InputStreamReader translacja bajtów na znaki OutputStreamWriter translacja znaków na bajty PrintWriter OutputStream z print() i println() PushbackReader InputStream z "unget" Potoki Pre-Definiowane Częścią pakietu java.lang jest klasa System. Dostarcza trzy zmienne potokowe (public, static): ● System.in: InputStream standardowe urządzenie wejściowe (klawiatura) ● System.out: PrintStream standardowe urządzenie wyjściowe (konsola) ● System.err: PrintStream standardowe urządzenie błędów (konsola) Czytanie z Konsoli Tradycyjnie – przez potok bajtowy. Preferowana metoda – potok znakowy jest łatwiejszy w konserwacji i internacjonalizacji. ● zamiana potoku bajtowego na znakowy InputStreamReader isr = new InputStreamReader(System.in) ● otoczenie potoku znakowego potokiem buforowanym BufferedReader br = new BufferedReader(isr) wymaga Reader, dostaje InputStreamReader Czytanie Znaków Czytanie znaków z BufferedReader: int read() throws IOException Czyta znak z potoku wejściowego: ● zwraca liczbę całkowitą ● zwraca -1 jeśli koniec potoku Wejście jest buforowane – przekazanie danych do programu po naciśnięciu ENTER. Czytanie Znaków: Przykład import java.io.*; class BRRead { public static void main(String args[]) throws IOException { char c; BufferedReader br = new BufferedReader( new InputStreamReader(System.in)); System.out.println("Enter characters, 'q' to quit."); do { c = (char) br.read(); System.out.println(c); } while(c != 'q'); } } Czytanie Łańcuchów Czytanie ciągu znaków z klawiatury: String readLine() throws IOException Czytanie Łańcuchów: Przykład import java.io.*; class BRReadLines { public static void main(String args[]) throws IOException { BufferedReader br = new BufferedReader( new InputStreamReader(System.in)); String str; System.out.println("Enter lines of text."); System.out.println("Enter 'stop' to quit."); do { str = br.readLine(); System.out.println(str); } while(!str.equals("stop")); } } Czytanie Łańcuchów: Inny Przykład import java.io.*; class TinyEdit { public static void main(String args[]) throws IOException { BufferedReader br = new BufferedReader( new InputStreamReader(System.in)); String str[] = new String[100]; System.out.println("Enter lines of text."); System.out.println("Enter 'stop' to quit."); Czytanie Łańcuchów: Inny Przykład for(int i=0; i<100; i++) { str[i] = br.readLine(); if(str[i].equals("stop")) break; } System.out.println("\nHere is your file:"); } } for(int i=0; i<100; i++) { if(str[i].equals("stop")) break; System.out.println(str[i]); } Pisanie na Konsolę Najłatwiej przez print() i println(). Jest też nisko-poziomowy void write(int byteval) class WriteDemo { } public static void main(String args[]) { int b = 'A'; System.out.write(b); System.out.write('\n'); } Mimo iż argument jest typu int, wypisywane jest tylko osiem najmniej znaczących bitów argumentu. Preferowana Metoda Pisania Przez znakową klasę PrintWriter: PrintWriter( OutputStream outputStream, boolean flushOnNewline) outputStream to potok wyjściowy (System.out) ● flushOnNewline – czy potok jest czyszczony za każdym wywołaniem println() ● PrintWriter dostarcza print() i println(). Jeśli nie typ prosty, wywoływany jest toString(). Pisanie na Konsolę: Przykład import java.io.*; public class PrintWriterDemo { } public static void main(String args[]) { PrintWriter pw = new PrintWriter(System.out, true); pw.println("This is a string"); int i = -7; pw.println(i); double d = 4.5e-7; pw.println(d); } Czytanie/Pisanie do Plików Bajtowe potoki do obsługi plików. Można jest otaczać potokami znakowymi. Otwarcie pliku do czytania/pisania: ● ● FileInputStream(String fileName) throws FileNotFoundException FileOutputStream(String fileName) throws FileNotFoundException Zamknięcie pliku po obsłudze: void close() throws IOException Czytanie/Pisanie do Plików Czytanie z pliku: int read() throws IOException Zwraca -1 gdy koniec pliku. Pisanie do pliku: void write(int byteval) throws IOException Mimo iż argument jest typu int, wypisywane jest tylko osiem najmniej znaczących bitów argumentu. Czytanie Pliku: Przykład import java.io.*; class ShowFile { public static void main(String args[]) throws IOException { int i; FileInputStream fin; try { fin = new FileInputStream(args[0]); } catch(FileNotFoundException e) { System.out.println("File Not Found"); return; } catch(ArrayIndexOutOfBoundsException e) { System.out.println("Usage: ShowFile File"); return; } Czytanie Pliku: Przykład do { i = fin.read(); if(i != -1) System.out.print((char) i); } while(i != -1); } } fin.close(); Pisanie do Pliku: Przykład import java.io.*; class CopyFile { public static void main(String args[]) throws IOException { int i; FileInputStream fin; FileOutputStream fout; try { try { fin = new FileInputStream(args[0]); } catch(FileNotFoundException e) { System.out.println("File Not Found"); return; } Pisanie do Pliku: Przykład try { fout = new FileOutputStream(args[1]); } catch(FileNotFoundException e) { System.out.println( "Error Opening Output File"); return; } } catch(ArrayIndexOutOfBoundsException e) { System.out.println( "Usage: CopyFile From To"); return; } Pisanie do Pliku: Przykład try { do { i = fin.read(); if(i != -1) fout.write(i); } while(i != -1); } catch(IOException e) { System.out.println("File Error"); } } } fin.close(); fout.close(); Wejściowy Potok Bajtowy Metody definiowane przez klasę InputStream: ● int available() - liczba bajtów do czytania ● void close() - zamyka potok ● void mark(int numBytes) – oznacza bieżące miejsce w potoku do przeczytania numBytes znaków ● boolean markSupported() - czy potok wspiera mark/reset ● int read() - zwraca następny dostępny bajt, lub -1 ● int read(byte buffer[]) próbuje czytać znaki do bufora, zwraca ilość przeczytanych lub -1 ● int read(byte buffer[],int off,int num) – jak wyżej, ale zapisuje z przesunięciem off Wejściowy Potok Bajtowy, Ciąg Dalszy void reset() – przesuwa wskaźnik pliku do poprzednio zaznaczonej pozycji ● long skip(long numBytes) – przeskakuje numBytes bajtów z potoku wejściowego, zwraca faktyczną liczbę ignorowanych bajtów ● Wyjściowy Potok Bajtowy Metody definiowane przez klasę OutputStream: ● void close() - zamyka potok ● void flush() – czyści bufor na wyjście ● void write(int b) – pisze pojedynczy bajt to potoku wyjściowego ● void write(byte buffer[]) - zapisuje całą tablicę bajtów do potoku wyjściowego ● void write(byte buffer[],int off,int num) – zapisuje do potoku wyjściowego num bajtów z tablicy bajtów buffer, począwszy od indeksu off Pliki Klasa File nie operuje na zawartości plików (potoku), a na samych plikach: ● dostęp ● ścieżka ● data i czas ● katalogi i podkatalogi Konstruktory: File(String directoryPath) File(String directoryPath, String filename) File(File dirObj, String filename) Pliki: Przykład import java.io.File; class FileDemo { static void p(String s) { System.out.println(s); } public static void main(String args[]) { File f1 = new File("C:/temp/COPYRIGHT"); p("File Name: " + f1.getName()); p("Path: " + f1.getPath()); p("Abs Path: " + f1.getAbsolutePath()); p("Parent: " + f1.getParent()); p(f1.exists() ? "exists" : "does not exist"); Pliki: Przykład } } p(f1.canWrite() ? "is writeable" : "is not writeable"); p(f1.canRead() ? "is readable" : "is not readable"); p("is " + (f1.isDirectory() ? "" : "not" + " a directory")); p(f1.isFile() ? "is normal file" : "might be a named pipe"); p(f1.isAbsolute() ? "is absolute" : "is not absolute"); p("File last modified: " + f1.lastModified()); p("File size: " + f1.length() + " Bytes"); Katalog Katalog jest plikiem z listą innych plików/katalogów. Czy plik jest katalogiem? boolean isDirectory() Lista plików w katalogu: String[] list() Katalog: Przykład import java.io.File; class DirList { public static void main(String args[]) { String dirname = "C:/temp"; File f1 = new File(dirname); if (f1.isDirectory()) { System.out.println( "Directory of " + dirname); String s[] = f1.list(); Katalog: Przykład } } for (int i=0; i < s.length; i++) { File f = new File(dirname + "/" + s[i]); if (f.isDirectory()) { System.out.println(s[i] + " is a directory"); } else { System.out.println(s[i] + " is a file"); } } } else { System.out.println(dirname + " is not a directory"); }