Przygotował: Jacek Sroka 1 Java SE Strumienie
Przygotował: Jacek Sroka 2 Wielkość systemu we/wy Różne media konsola, pliki, połączenia sieciowe, łącza między procesami, itp. Różne sposoby sekwencyjnie, z dostępem swobodnym, z buforem, binarnie, znakowo, linia po linii Dodatkowe przetwarzanie kompresja, szyfrowanie Wzorzec Decorator
Przygotował: Jacek Sroka 3 Strumienie (ang. Stream) Uniwersalny pomysł stosowany w większości języków programowania InputStream, OutputStream - do danych binarnych Reader, Writer - do danych znakowych od wersji 1.1 Obie hierarchie się nawzajem uzupełniają łatwa konwersja strumieni binarnych na znakowe
Przygotował: Jacek Sroka 4 Podstawowe rodzaje strumieni File[Input Output]Stream ByteArray[Input Output]Stream Odczytywanie i zapisywanie plików dyskowych File[Reader Writer] Bufor w pamięci oparty na tablicy bajtów/znaków CharArray[Reader Writer] Bufor w pamięci oparty na napisie (implementacja posługuje się obiektem StringBuffer) StringBufferInputStream (nie ma odmiany output i jest deprecated) String[Reader Writer] Łącze do komunikacji między procesami Piped[Input Output]Stream Piped[Reader Writer]
Przygotował: Jacek Sroka 5 Korzystanie ze strumieni W obu hierarchiach klas występują metod read() i write() w najprostszej wersji odczytują/zapisuję jeden bajt/znak (a tak naprawdę wartość int reprezentującą ten znak) Po użyciu strumień należy zamknąć metodą close() dla niektórych zasobów obowiązują limity na liczbę otwartych egzemplarzy najlepiej używać bloków finally
Przygotował: Jacek Sroka 6 Przykład import java.io.filereader; import java.io.ioexception; public class ZnakPoZnaku { public static void main(string[] args) throws IOException { // wersja dla Linuxa FileReader rd = new FileReader("/tmp/io_test.txt"); // wersja dla Windows // FileReader rd = new FileReader("c:\\io_test.txt"); try { int i; // Reader.read() zwraca wartość z przedziału 0 to 65535, // jeżeli odczyt się powiódł lub -1 jak nie while ((i = rd.read())!= -1) System.out.print((char) i); finally { rd.close();
Przygotował: Jacek Sroka 7 Konwersja strumieni binarnych na znakowe Jest możliwa dzięki InputStreamReader i OutputStreamWriter Przydatna np. przy kompresji danych
Przygotował: Jacek Sroka 8 Przykład import java.io.*; public class KonwersjaStrumieni { public static void main(string[] args) throws IOException { String napis = "Test strumieni.\nąćęłńóśźż\n"; ByteArrayOutputStream os = new ByteArrayOutputStream(); // OutputStream jest przekrztałcany na Writer Writer wr = new OutputStreamWriter(os); wr.write(napis); wr.close(); ByteArrayInputStream is = new ByteArrayInputStream(os.toByteArray()); // InputStream jest przekształcany na Reader Reader rd = new InputStreamReader(is); int i; while ((i = rd.read())!= -1) System.out.print((char) i); rd.close();
Przygotował: Jacek Sroka 9 Kodowanie znaków Znaki w Javie są kodowane w Unicode od wersji 1.5 niektóre znaki zajmują dwie wartości typu char (4 bajty) InputStreamReader oraz OutputStreamWriter wykonują odpowiednio konwersję z oraz na domyślne kodowanie dla danej platformy jeżeli używamy konstruktorów bezparametrowych wskazane przez nas kodowanie jeżeli używamy konstruktorów przeciążonych Domyślne kodowanie jest również stosowane przez FileWriter i FileReader implementacja korzysta ze strumienie bin. i przekształca je na znakowe żeby obsługiwać pliki w innym kodowaniu trzeba samemu przekształcić strumienie binarne
Przygotował: Jacek Sroka 10 Konkatenacja strumieni SequenceInputStream pozwala używać grupy strumieni InputStream Dwa rodzaje konstruktorów dwa obiekty InputStream Enumeration<? extends InputStream>
Przygotował: Jacek Sroka 11 Przykład import java.io.*; public class Test2 { public static void main(string[] args) throws IOException { String dane1 = "Dane dla bufora 1.\nąćęłńóśźż\n"; String dane2 = "Dane dla bufora 2.\nąćęłńóśźż\n"; // getbytes() zwraca tablicę bajtów reprezentujących kolejne znaki // w domyślnym kodowaniu platformy (są też wersje przeciążone) ByteArrayInputStream is1 = new ByteArrayInputStream(dane1.getBytes()); ByteArrayInputStream is2 = new ByteArrayInputStream(dane2.getBytes()); SequenceInputStream seq = new SequenceInputStream(is1, is2); Reader rd = new InputStreamReader(seq); int i; while ((i = rd.read())!= -1) System.out.print((char) i);
Przygotował: Jacek Sroka 12 Wzorzec Dekorator
Przygotował: Jacek Sroka 13 Podstawowe rodzaje dekoratorów Operacje przechodzą przez bufor (można wymusić wysłanie niepełnego bufora przy pomocy metody flush()) Buffered[Input Output]Stream Buffered[Reader Writer] Wiele metod do wypisywania danych w czytelny dla człowieka sposób (dwie odmiany metod print() i println()) (posiadają dodatkowe konstruktory, żeby uprościć otwieranie pliku i dekorowanie go buforem) (nie przepuszczają IOException, trzeba spradzać metodą checkerror()) PrintStream PrintWriter Przydatne przy budowie kompilatora (ostatnio odczytane dane można zawrócić do specjalnego bufora przy pomocy metody unread()) PushBackInputStream (deprecated) PushBackReader (dodają metodę getlinenumber() zwracającą liczbę odczytanych do tej pory linii) LineNumberInputStream LineNumberReader
Przygotował: Jacek Sroka 14 Dekoratory strumieni binarnych Data[Input Output]Stream przesyłanie wartości typów podstawowych i napisów Object[Input Output]Stream przesyłanie obiektów implementujących java.io.serializable Checked[Input Output]Stream wyliczanie sumy kontrolnej dostępne algorytmy Adler32 i CRC32 z pakietu java.util.zip GZIP[Input Output]Stream kompresja GZIP z pakietu java.util.zip Zip[Input Output]Stream kompresja ZIP z pakietu java.util.zip Cipher[Input Output]Stream szyfrowanie za pomocą klasy Cipher z pakietu java.crypto
Przygotował: Jacek Sroka 15 Przykład public class TestDekoratorów { public static void main(string[] args) throws IOException { String nazwapliku = "/tmp/io_test.txt"; DataOutputStream os = new DataOutputStream( new BufferedOutputStream ( new FileOutputStream(nazwaPliku))); os.writeboolean(true); os.writeint(1234567890); os.writedouble(math.pi); os.writeutf("test strumieni.\nąćęłńóśźż\n"); os.close();// wykonuje flush() DataInputStream is = new DataInputStream( new BufferedInputStream ( new FileInputStream(nazwaPliku))); Boolean b = is.readboolean(); Integer i = is.readint(); Double d = is.readdouble(); String str = is.readutf(); is.close(); System.out.printf("Odczytano: b=%s, i=%s, d=%s, str=%s", b, i, d, str);
Przygotował: Jacek Sroka 16 Bufor wielkości 10 bajtów: 1
Przygotował: Jacek Sroka 17 Bufor wielkości 10 bajtów: 1 0 12
Przygotował: Jacek Sroka 18 Bufor wielkości 10 bajtów: 1 0 12 73-106 2-46
Przygotował: Jacek Sroka 19 Bufor wielkości 10 bajtów: -5 1 084 1268 7325-106 24 2-46 63 9 33
Przygotował: Jacek Sroka 20... Bufor wielkości 10 bajtów: 116-5 84 32 115 68 25 24 0 35 84 101 115
Przygotował: Jacek Sroka 21 Przykład kompresja GZIP public class KompresjaGZIP { public static void main(string[] args) throws IOException { String nazwapliku = "/tmp/io_test.gzip"; BufferedOutputStream os = new BufferedOutputStream( new GZIPOutputStream( new FileOutputStream(nazwaPliku))); PrintWriter pw = new PrintWriter( new OutputStreamWriter(os)); pw.write("kompresja w Javie jest prosta"); pw.close(); // dekompresja BufferedInputStream is = new BufferedInputStream( new GZIPInputStream( new FileInputStream(nazwaPliku))); BufferedReader br = new BufferedReader( new InputStreamReader(is)); String s; while ( (s = br.readline())!= null ) System.out.println(s); br.close();
Przygotował: Jacek Sroka 22 Przykład kompresja ZIP int x; ZipOutputStream zos = new ZipOutputStream(new BufferedOutputStream(...)); for (int i = 1; i < args.length; i++) { System.out.println("Zapisywanie " + args[i]); BufferedInputStream in = new BufferedInputStream(new FileInputStream(...)); zos.putnextentry(new ZipEntry(args[i])); while ( (x = in.read())!= -1 ) zos.write(x); in.close(); zos.close(); ZipInputStream zis = new ZipInputStream(new BufferedInputStream(...)); ZipEntry ze; while ( (ze = zis.getnextentry())!= null ) { System.out.println(); System.out.println("Odczytywanie: " + ze); while ( (x = zis.read())!= -1 ) System.out.write(x); System.out.flush(); zis.close();
Przygotował: Jacek Sroka 23 Standardowe wejście/wyjście Pomysł pochodzi z systemów Unix pozwala łączyć programy w potoki przetwarzania zaadoptowany w innych systemach, m.in. Windows W Javie dostęp przez składowe klasy System na System.out i System.err przypisane są obiekt PrintStream System.in to zwykły InputStream wejście najczęściej opakowujemy w BufferedReader i używamy metody readline() Można wykonać przekierowanie setout(printstream) setin(inputstream) seterr(printstream)
Przygotował: Jacek Sroka 24 Nowe wejście/wyjście od Javy 1.4 zebrane w pakiecie java.nio.* podejście zbliżone do organizacji we/wy w systemach operacyjnych szybkie, ale pracochłonne i wymaga wiele uwagi efektywność starych bibliotek też wzrosła, bo zostały zaimplementowane przy pomocy nowych