SYSTEM WEJŚCIA-WYJŚCIA W JAVIE Autor:Jakub Piasecki Data powstania: Grudzień 2003 File- Klasa Reprezentuje ona albo nazwę konkretnego pliku, albo nazwę zbioru plików czyli katalogu Java traktuje katalogi i pliki w podobny sposób Korzystamy z biblioteki java.io.*; String list()- metoda która w przypadku katalogów zwraca tablice z nazwami plików znajdujących się w danym katalogu Przykładowy kod (katalogi I) Wypisanie zawartości katalogu: File sciezka = new File("Folder"); String[] lista = sciezka.list(); for(int i=0; i<lista.length; i++) System.out.println(lista[i]); File- metody String String String String getname()- zwraca nazwę pliku getpath()- zwraca ścieżkę pliku getAbsolutePath()-zwraca pełną ścieżkę pliku getParent()-zwraca ścieżkę nadrzędną boolean boolean boolean boolean boolean exists()– czy istnieje canWrite()- możliwość zapisu canRead()- możliwość czytania isFile()- czy plik isDirectory()- czy katalog File- metody c.d. boolean renameTo(File newName)- zmiana nazwy boolean mkdirs()- tworzenie ścieżki o dowolnej złożonosci boolean delete()- kasowanie pliku long length()– długość pliku long lastModified()– ostania modyfikacja Przykładowy kod (katalogi II) Tworzenie katalogu i zmiana jego nazwy File sciezka= new File("c:/katalog1"); File nowaSciezka=new File("c:/katlog2"); //tworzymy katalog sciezka.mkdirs(); //zmieniamy jego nazwę sciezka.renameTo(nowaSciezka); I/O- informacje podstawowe Java wykorzystuje pojęcie strumienia (ang. stream) Strumień- reprezentacja dowolnego źródła danych, jako obiektu zdolnego do wysyłania i odbierania porcji danych W Javie 1.1 zaszły istotne zmiany w stosunku do wcześniejszych wersji (cel: obsługa standardu Unicode) Rozróżniamy dwa rodzaje strumieni: tekstowe i binarne Do obsługi tekstowych korzystamy z hierarchii klas Reader i Writer Do obsługi binarnych korzystamy z hierarchii klas InputStream i OutputStream Reader i Writer Używamy do obsługi strumieni tekstowych Powstały w celu obsługi standardu Unicode Podział na dwie podstawowe klasy Reader oraz Writer, które posiadają metody read() i write() pozwalające na operacje czytania i zapisu bajtu lub tablicy bajtów(to samo InputStream i OutputStream) Nie korzystamy z tych metod bezpośrednio. Wykorzystują je klasy dziedziczące, które służą do obsługi konkretnych źródeł. Reader- możliwe źródła Tablica bajtów Obiekt String Plik Potok Sekwencja Strumieni Inne źródła(np. połączenia internetowe) Reader- Użyteczne Podklasy Klasa Działanie CharArrayReader Odczyt bajtów z tablicy Argument Konstruktora Tablica, z której czytamy bajty StringReader Konwertuje String do obiektu typu Reader Obiekt typu String FileReader Odczyt informacji z pliku Obiekt File FilterReader Dostarcza interfejs dla dekoratorów, poszerzających możliwości klas Reader Obiekt Reader Reader- Dekoratory klas Klasy Reader używamy w połączeniu z dekoratorami tworząc użyteczny interfejs Najczęściej stosowany to: BufferedReader- używamy go aby zapobiec fizycznemu odczytowi za każdym żądaniem kolejnych danych. Jako argument przyjmuje obiekt typu Reader. Zastosowanie go znacznie zwiększa wydajność Przykładowy kod (czytanie z pliku)(1/2) Czytanie z pliku i wyświetlenie na ekranie Konstrukcja z zagnieżdżoną instrukcją try pozwala na uniknięcie błędów, szczególnie wyróżnione w przykładzie zamknięcie strumienia niezależnie od błędów występujących podczas przetwarzania W celu większej przejrzystości w kolejnych przykładach strumienie będą zamykane w głównym bloku try. Należy jednak pamiętać, że przy pisaniu programu należy zastosować pełną konstrukcję. kod Przykładowy kod (czytanie z pliku)(2/2) try{ //tworzymy strumień Reader z obiektu File i dekorujemy go //za pomocą BufferedReader BufferedReader in = new BufferedReader(new FileReader(plik)); String s; //czytamy kolejne linie pliku za pomocą readline() try{ while((s=in.readLine())!=null) System.out.println(s); }catch(IOException e1){ System.err.println("Błąd przy przetwarzaniu"); }finally{ in.close(); //zamknięcie strumienia!!! } }catch(FileNotFoundException e2{ System.err.println("Brak pliku:"+ plik); } Writer- Użyteczne Podklasy Klasa Działanie Argument Konstruktora CharArrayWriter Tworzy bufor w pamięci Opcjonalnie rozmiar w którym umieszczone bufora są dane wysyłane do strumienia FileWriter Wysyła informacje do pliku String reprezentujący nazwę pliku lub obiekt File Writer- Zapis do strumieni PrintWriter- za pomocą tej klasy możemy zrealizować zapis danych danych w formie nadającej się do przeglądania. Posiada ona dwie ważne metody print() i println() BufferedWriter- za pomocą tego dekoratora możemy zwiększyć wydajność zapisu. Jako argument przyjmuje on obiekt typu Writer Przykładowy kod (zapis do pliku- prawidłowe zamknięcie strumienia) Odczytanie danych z klasy String i zapis do pliku File plik = new File("test1.txt"); String s="Pierwsza Linia \nDruga Linia \nKoniec"; String s2; BufferedReader in = new BufferedReader(new StringReader(s)); try{ PrintWriter out = new PrintWriter( new BufferedWriter(new FileWriter(plik))); //czytamy ze strumienia in i zapisujemy do strumienia out while((s2=in.readLine())!=null) out.println(s2); out.close(); }catch(IOException e1){} } InputStream i OutputStream Spełniały role głównych klas I/O zanim powstały klasy Reader i Writer w Javie1.1 Posiadają podklasy analogiczne do podklas Reader i Writer, których nazwy w miejscu wyrazów „Reader” i „Writer” mają wyrazy „InputStream” i „OutputStream” np. FileInputStream zamiast FileReader Wciąż używa się niektórych podklas do operacji zorientowanych bajtowo. Szczególnie DataInputStream i DataOutputStream Istnieje możliwość konwersji obiektów tego typu do obiektów Reader i Writer za pomocą adapterów InputStreamReader oraz OutputStreamWriter DataInputStream i DataOutputStream Są podklasami InputStream i OutputStream DataOutputStream umożliwia zapis i danych w postaci która może być odczytana jedynie za pomocą DataInputStream Umożliwiają odczyt i zapis danych podstawowych niezależnie od platformy systemowej Stosują metody typu: readFloat(), readDouble(), writeInt() Przy wczytywaniu danych trzeba znać ich kolejność w strumieniu writeUTF(), readUTF()- metody stosowane do zapisu i odczytu obiektów String Przykładowy kod (zapis do pliku i odzyskiwanie danych) zapis do pliku i odzyskiwanie danych try{ DataOutputStream out = new DataOutputStream(new FileOutputStream("Data.dat")); out.writeDouble(13.1231); out.writeUTF("to jest obiekt string"); out.close(); //to był zapis, teraz odczyt DataInputStream in = new DataInputStream(new FileInputStream("Data.dat")); System.out.println(in.readDouble()); System.out.println(in.readUTF()); in.close(); }catch(IOException e1){}; } Standardowe wejście-wyjście Termin odnosi się do koncepcji wywodzących się z Unixa, stosowanej potem w innych systemach operacyjnych Dane wejściowe mogą pochodzić ze standardowego wejścia, a dane wyjściowe program może wysyłać na standardowe wyjście i standardowe wyjście błędów Wyjście jednego programu może być wejściem drugiego System.in, System.out ,System.err- obiekty Obiekt System.out jest standardowo opakowany w obiekt Printstream Dwa pozostałe obiekty należy samemu opakować w celu użycia System.in jest obiektem hierarchii InputStream dlatego aby skonwertować go do Reader używamy adaptera InputStreamReader Przykładowy kod (czytanie ze standardowego wejścia) czytanie danych ze standardowego wejścia i zapis do obiektu String try{ //konwertujemy System.in do obiektu Reader InputStreamReader ir= new InputStreamReader(System.in); BufferedReader in = new BufferedReader(ir); String s1,s2; //wprowadzenie pustego wiersza kończy pętlę while((s2=in.readLine())!=null && s2.length()!=0) s1+=s2; System.out.println(s1); }catch(IOException e1){} Przekierowanie Standardowego wejścia-wyjścia Używamy np. kiedy chcemy przekierować do pliku dane które normalnie byłyby skierowane na konsole setIn(InputStream), setOut(PrintStream),setErr(PrintStream)- metody klasy System służące do przekierowań Operacje przekierowań to operacje bajtowe dlatego używamy klas klas Input i OutputStream Przykładowy kod (przekierowanie standardowego wejścia do pliku) przekierowanie standardowego wyjścia do pliku try{ PrintStream mojeOut= new PrintStream( new BufferedOutputStream( new FileOutputStream("test.txt"))); System.setOut(mojeOut); System.out.println("To będzie zapisane w pliku"); mojeOut.close(); System.setOut(System.out); } catch(IOException e1){} RandomAccesFile- Klasa Jest używana do obsługi plików zawierających rekordy o znanym rozmiarze Jest to zupełnie oddzielna klasa nie korzysta z funkcji Input i OutputStream Swobodny dostęp- możemy poruszać się w pliku „do przodu” i „w tył” seek()-metoda pozwalająca na przemieszczenie się do danego miejsca length()- maksymalna długość pliku Jako drugi argument konstruktora przyjmuje tryb w jakim otieramy plik "rw"- zapis i odczyt lub "r"- tylko zapis Przykładowy kod (odczyt z plików o swobodnym dostępie) Zapis i odczyt z plików o swobodnym dostępie try{ RandomAccessFile rf = new RandomAccessFile("test.dat","rw"); for(int i=0; i<10; i++) rf.writeInt(i); rf.close(); rf = new RandomAccessFile("test.dat","rw"); rf.seek(4*5); //writeInt wstawi 13 w miejsce 5 rf.writeInt(13); rf.close(); rf = new RandomAccessFile("test.dat","rw"); for(int i=0; i<10; i++) System.out.println(rf.readInt()); rf.close(); }catch(IOException e1){}; } Properties Mogą być użyte do zapisywania i wczytywania ustawień przy każdym uruchomieniu programu Properties- obiekt składa się z par klucz/wartość zapisanych w postaci String Możemy skierować zawartość obiektu do strumienia(pociąga to za sobą możliwość zapisu do pliku) Możemy do obiektu Properties skierować zawartość strumienia(wczytanie z pliku) Wygodny system umożliwiający w prosty sposób konfigurację ustawień programu Poprzez prostą modyfikację wartości par klucz/wartość w pliku możemy łatwo zmienić konfigurację Properties -metody load(InputStream in)-wczytanie zawartości ze strumienia store(OutputStream out,String nagłowek)- zapis wartości do strumienia dodawany jest nagłówek getProperty(String klucz)- zwraca wartość dla danego klucza setProperty(String klucz,String wartość)ustawienie wartości dla danego klucza Możliwe jest stworzenie wartości domyślnych, które możemy wczytać w razie braku wartości dla danego klucza w danym obiekcie Properties (odsyłam do dokumentacji Javy) Przykładowy kod (ustawienie wartości Properties zapis i wczytanie z pliku) String userLogin; Properties props1= new Properties(); props1.setProperty("login","piasecki"); props1.setProperty("nr_grupy","5"); try{ FileOutputStream out =new FileOutputStream("konfig.txt"); props1.store(out,"--Plik Konfiguracyjny--"); //zapis wartości out.close(); }catch(IOException e){} Properties props2= new Properties(); try{ FileInputStream in =new FileInputStream("konfig.txt"); props2.load(in); //wczytanie wartości in.close(); }catch(IOException e){} userLogin=props2.getProperty("login"); System.out.println("User Login: "+userLogin); Przykładowy plik konfiguracyjny Zawartość: #--Plik Konfiguracyjny-#Thu Dec 04 21:10:26 CET 2003 login=piasecki nr_grupy=5 System Properties Zastępują pomysł zmiennych środowiskowych specyficznych dla każdej platformy na której uruchamiamy programy Java System.getProperties()-metoda zwraca obiekt Properties getProperty()- zwraca String reprezentujący wartość danej właściwości (ang. property) propertyNames()-wywołana na obiekcie typu Properties zwraca typ wyliczeniowy Przykładowy kod (użycie SystemPropeties) Wypisanie na ekran wartości SystemProperties Properties props = System.getProperties(); Enumeration propNazwy =props.propertyNames(); while (propNazwy.hasMoreElements()){ String propNazwa =(String)propNazwy.nextElement(); String property =(String)props.getProperty(propNazwa); System.out.println("Property "+propNazwa+": "+property); } Properties- wynik Niektóre properties uzyskane za pomocą propgramu Property java.runtime.name: Java(TM) 2 Runtime Environment, Standard Edition Property sun.boot.library.path: C:\Program Files\JavaSoft\JRE\1.3.1_09\bin Property java.vm.version: 1.3.1_09-b03 Property java.vm.vendor: Sun Microsystems Inc. Property java.vendor.url: http://java.sun.com/ Property java.vm.specification.name: Java Virtual Machine Specification Property user.dir: E:\eclipse-SDK-2.1.1-win32\eclipse\workspace\Pliki Property java.runtime.version: 1.3.1_09-b03 Property java.io.tmpdir: C:\DOCUME~1\Kuba\USTAWI~1\Temp\ Property java.vm.specification.vendor: Sun Microsystems Inc. Property os.name: Windows XP Property java.library.path: C:\Program Files\JavaSoft\JRE\1.3.1_09\bin;.;C:\WINDOWS\System32;C:\WINDOWS;C:\WINDOWS\sy stem32;C:\WINDOWS;C:\WINDOWS\System32\Wbem Property java.specification.name: Java Platform API Specification Property java.class.version: 47.0 Property os.version: 5.1 Property user.home: C:\Documents and Settings\Kuba Property java.home: C:\Program Files\JavaSoft\JRE\1.3.1_09 Property user.region: PL Property sun.cpu.isalist: pentium i486 i386 Sockets Socket- jest jedną z „końcówek” dwustronnej komunikacji pomiędzy dwoma programami działającymi w sieci. Jest związany z numerem portu i IP komputera więc warstwa TCP może zidentyfikować aplikację do której przesyłane są dane Używamy ich kiedy chcemy stworzyć model komunikacji pomiędzy dwoma programami w sieci np. aplikację typu klientserwer po każdej stronie znajduje się soket, do którego klient i serwer mogą zapisywać i z którego mogą odczytywać informacje Biblioteka java.net dostarcza dwie klasy Socket i ServerSocket- które są odpowiedzialne za połączenie po stronie klienta i serwera Można z niego czytać jak ze strumienia Wykorzystane Materiały „Thinking in Java” Bruce Eckel „The JavaTM Tutorial” Copyright 1995-2003 Sun Microsystems „ JavaTM Programming Language” Copyright 2002 Sun Microsystems Koniec