Języki i Techniki Programowania II Wykład 6 Wejście/Wyjście
Podstawowy podział strumieni Strumienie: Bajtowe: (Stream) Wejściowe (InputStream, FilterInputStream...) Wyjściowe (OutputStream, FilterOutputStream...) Znakowe (Reader, Writer) Wejściowe (InputStreamReader...) Wyjściowe (OutputStreamReader...)
Wejściowe Strumienie Bajtowe
Wejściowe Strumienie Bajtowe InputStream przodek hierarchii, istotne metody: int read(), int read(byte[]), int read(byte[], int, int) PipedInputStream służy do komunikacji wewnątrz programu ByteArrayInputStream strumień czytający z tablicy FilterInputStream przodek strumieni wprowadzających dodatkową funkcjonalność DataInputStream operujące na typach prymitywnych BufferedInputStream strumień buforowany GZIPInputStream strumień dekompresujący w locie dane przez niego przechodzące SequenceInputStream skleja kolejne strumienie
Wyjściowe Strumienie Bajtowe
Wyjściowe Strumienie Bajtowe OutputStream przodek hierarchii, istotne metody: write(int), write(byte[]), write(byte[],int,int) PipedOutputStream służy do komunikacji wewnątrz programu ByteArrayOutputStream strumień piszący do tablicy FilterOutputStream przodek strumieni wprowadzających dodatkową funkcjonalność DataOutputStream operujące na typach prymitywnych BufferedOutputStream strumień buforowany GZIPOutputStream strumień kompresujący w locie dane przez niego przechodzące FileOutputStream strumień piszący do pliku
Wyjściowe Strumienie Znakowe
Wyjściowe Strumienie Znakowe Writer przodek hierarchii; istotne metody: write(int), write(char[]), write(string) BufferedWriter buforowany strumień znakowy CharArrayWriter strumień piszący do tablicy znaków PipedWriter analogiczny do PipedOutputStream OutputStreamWriter połączenie strumienie znakowych i bajtowych FileWriter strumień skierowany do pliku PrintWriter podobny do PrintOutputStream, ale nie dysponuje metodami do obsługi byte[]
Wejściowe Strumienie Znakowe
Wejściowe Strumienie Znakowe Reader przodek hierarchii; istotne metody: read(int), read(byte[]), read(byte[],int,int) BufferedReader buforowany strumień znakowy: podstawowa metoda String readline() LineNumberReader strumień zliczający numery linii CharArrayReader strumień piszący do tablicy znaków PipedReader analogiczny do PipedOutputStream InputStreamReader połączenie strumienie znakowych i bajtowych FileReader strumień skierowany do pliku
Wzorzec Decorator
Wzorzec Decorator Inna nazwa: Wrapper Zastosowania: Zmienne w czasie zadania dla klas Gdy dziedziczenie jest niepraktyczne (np. w przypadku zagrożenia eksponencjalnym wzrostem ilości typów) Zalety: Dynamiczny charakter zachowania Uproszczona hierarchia, korzeń struktury odciążony Wady: Brak kontroli typów, system bardziej złożony wiele obiektów o bardziej zróżnicowanym zachowaniu
Standardowe Wejście String s; BufferedReader br= new BufferedReader( new InputStreamReader(System.in)); while ( (s = br.readline())!= null ) { System.out.println(s); }
CSV 19.99, 12, Java T-shirt 9.99, 8, Java Mug...
Przetwarzanie pliku CSV String s; BufferedReader br= new BufferedReader( new InputStreamReader( new FileInputStream( data.csv ))); while ( (s = br.readline())!= null ) { String fields [] = s.split(, ;,3); for (int i=0;i<fields.length;i++) fields[i]=fields[i].trim();... }
DataOutputStream DataOutputStream out = new DataOutputStream( new FileOutputStream( plik.dat )); for (int i = 0; i < prices.length; i ++) { out.writedouble(prices[i]); out.writeint(units[i]); out.writechars(descs[i]); } out.close();
DataInputStream DataInputStream in = new DataInputStream( new FileInputStream("plik.dat")); try { while (true) { price = in.readdouble(); unit = in.readint(); char chr; desc = new StringBuffer(20); char linesep = System.getProperty("line.separator").charAt(0);
DataInputStream while ((chr = in.readchar()!= linesep) { } desc.append(chr); System.out.println("You've ordered " + unit + " units of + desc + " at $" + price); total = total + unit * price; } } catch (EOFException e) { } System.out.println("For a TOTAL of: $" + total); in.close();
Pipe Streams BufferedReader in = new BufferedReader(source); PipedWriter pipeout = new PipedWriter(); PipedReader pipein = new PipedReader(pipeOut); PrintWriter out = new PrintWriter(pipeOut); new WorkingThread(out, in).start();
File Streams Strumienie pracujące na plikach: FileInputStream FileOutputStream FileReader FileWriter Konstruktory przyjmują: obiekt File na którym można operować String z nazwą pliku
System plików Klasa File słuzy do pracy z systemem plików, metody: isdirectory() isfile() list() canread() canwrite() getpath() getparent() delete()
Random Access File new RandomAccessFile("data.txt", "r"); int skipbytes(int) void seek(long) long getfilepointer()
Zastosowanie wzorca Decorator String s; BufferedReader br= new BufferedReader( new InputStreamReader( new GZIPInputStream( new FileInputStream( new File( data.txt.gz ))))); while ( (s = br.readline())!= null ) { System.out.println(s); }
Kodowanie znaków Wewnętrzne kodowanie Javy to UTF-16 znaki U+0000 to U+FFFF określane jako Basic Multilingual Plane (BMP). (piszemy literały jako \ubb24 np. Character.isLetter('\uD840')) Dla ideogramów: pary znaków high-surrogates range, (\ud800-\udbff) oraz low-surrogates range (\udc00-\udfff) ALE TO NIE MA ŻADNEGO ZNACZENIA!!! Domyślnie jest stosowane modified UTF-8
Kodowanie znaków Modified UTF8 zero kodowane jest dwubajtowo 0xc0 0x80 znak 1-127 1 bajt, najwyższy bit 0 znak 128-2047 2 bajty, starszy bajt na najwyższe bity 110, młodszy najwyższe bity 10 znak 2048-65535 - starszy bajt na najwyższe bity 1110, młodsze najwyższe bity 10 Powyżej: zamiast 4 bajtów, przechodzi na UTF-16, a poszczególne 16bitowe znaki następnie kodowane są przez CESU-8 - co daje 6 bajtów
Kodowanie znaków new BufferedReader( new InputStreamReader( new BufferedInputStream(in,2048), "UTF-8" //kodowanie: CP1250, ISO8859-2 ), 128 ) SortedMap<String,Charset> Charset.availableCharsets() System.getProperty("file.encoding")
Serializacja package java.io; public interface Serializable { // there's nothing in here! }; Zapisywane jest: klasa sygnatura klasy wszystkie pola nie-transient, i nie statyczne
Serializacja class Token implements Serializable { int i; } FileOutputStream out = new FileOutputStream("data.dat"); ObjectOutputStream s = new ObjectOutputStream(out); s.writeobject("today"); s.writeobject(new Date()); s.writeobject(new Token()); s.flush();
Serializacja FileInputStream in = new FileInputStream("data.dat"); ObjectInputStream s = new ObjectInputStream(in); String today = (String)s.readObject(); Date date = (Date)s.readObject(); Token t = (Token) s.readobject();
Externalizacja package java.io; public interface Externalizable extends Serializable { public void writeexternal(objectoutput out) throws IOException; } public void readexternal(objectinput in) throws IOException, java.lang.classnotfoundexception;
Serializacja Konstruktor bezparametrowy nie jest wołany. Chyba że z nieserializowalnych przodków. powinno być: static final long serialversionuid = 42L;
Serializacja public class MyExternalizable implements Externalizable { private String username; private String password; private Integer roll; public MyExternalizable(String username, String password, Integer roll) { this.username = username; this.password = password; this.roll = roll; }
Serializacja @Override public void writeexternal(objectoutput oo) throws IOException { oo.writeobject(username); oo.writeobject(roll); } @Override public void readexternal(objectinput oi) throws IOException, ClassNotFoundException { username = (String)oi.readObject(); roll = (Integer)oi.readObject(); }
java.nio NIO new I/O albo non-blocking I/O Wprowadzony w Javie 1.4 alternatywny mechanizm do java.io nieblokujące operacje I/O. Elementy: Buffers kontenery danych (także: mapowane do pamięci) Channels mechanizmy operowania na danych Selectors mechanizmy wybierania kanałów dostępnych (gotowych do operacji we/wy)
The C10K problem Ile połączeń może obsłużyć 1 web server? 1 połączenie na wątek x 20+ wątków kilka-naście/dziesiąt połączeń 500 połączeń na wątek x 20 wątków 10k połączeń
java.nio Java.IO Strumienie: świetne do budowania filtrów, przekształceń Strumienie: pracują na pojedynczych bajtach wolne Java.NIO Buffers: praca na blokach danych szybkie Channels: operacje są łączone w kanały nie blokują w oczekiwaniu na dane Selectors: wybór kanałów
java.nio http://tutorials.jenkov.com
java.nio Buffer ma: Capacity pojemność Limit koniec gdzie można pisać/czytać Position obecne położenie Mark miejsce dokąd przesuwa pozycję reset() 0 <= mark <= position <= limit <= capacity
java.nio Buffer ma: put(), get() - także (albo głównie) z argumentami tablicowymi clear() - gotuje buffer na czytanie do kanału albo na put(). limit:=capacity; position:=0 flip() - gotuje buffer na pisanie z kanału albo na get(). limit:=position;position=0 rewind() - position=0, gotuje do czytania jeszcze raz Chaining: b.flip().position(23).limit(42);
java.nio Buffer, cykl przetwarzania Pisanie do Buffer buffer.flip() Czytanie z Buffer buffer.clear() lub buffer.compact()
java.nio Buffer, cykl przetwarzania Pisanie do Buffer buffer.flip() Czytanie z Buffer buffer.clear() lub buffer.compact()
java.nio Buffer, compact buf.clear(); // Prepare buffer for use for (;;) { if (in.read(buf) < 0 &&!buf.hasremaining()) break; // No more bytes to transfer buf.flip(); out.write(buf); buf.compact(); // In case of partial write }
java.nio Channels http://tutorials.jenkov.com
java.nio Channels scatterring read ByteBuffer header = ByteBuffer.allocate(128); ByteBuffer body = ByteBuffer.allocate(1024); ByteBuffer[] bufferarray = { header, body }; channel.read(buffers); http://tutorials.jenkov.com
java.nio Channels gathering write ByteBuffer header = ByteBuffer.allocate(128); ByteBuffer body = ByteBuffer.allocate(1024); //write data into buffers ByteBuffer[] bufferarray = { header, body }; channel.write(buffers); http://tutorials.jenkov.com
java.nio RandomAccessFile afile = new RandomAccessFile("data/nio-data.txt", "rw"); FileChannel inchannel = afile.getchannel(); ByteBuffer buf = ByteBuffer.allocate(48); int bytesread = inchannel.read(buf); while (bytesread!= -1) { System.out.println("Read " + bytesread); buf.flip(); while(buf.hasremaining()){ System.out.print((char) buf.get()); } buf.clear(); bytesread = inchannel.read(buf); } afile.close();
java.nio Selectors Selector selector = Selector.open(); channel.configureblocking(false); SelectionKey key = channel.register(selector, SelectionKey.OP_READ); http://tutorials.jenkov.com
while(true) { int readychannels = selector.select(); if(readychannels == 0) continue; Set<SelectionKey> selectedkeys = selector.selectedkeys(); Iterator<SelectionKey> keyiterator = selectedkeys.iterator(); while(keyiterator.hasnext()) { SelectionKey key = keyiterator.next(); if(key.isacceptable()) { // a connection was accepted by a ServerSocketChannel. } else if (key.isconnectable()) { // a connection was established with a remote server. } else if (key.isreadable()) { // a channel is ready for reading } else if (key.iswritable()) { // a channel is ready for writing } keyiterator.remove(); } }
java.nio 2 NIO2 more new I/O np. java.nio.file Wprowadzony w Javie 1.7 rozbudowa mechanizmu do java.io nieblokujące operacje I/O. AsynchronousSocketChannel, AsynchronousServerSocketChannel, AsynchronousFileChannel, AsynchronousDatagramChannel Obsługa przez klasy Future Lepsza obsługa katalogów i ścieżek Monitorowanie zmian w pliku Etc...