I/O - srautai OP2, ver. 2009-11-25. Paruošė: R.Vaicekauskas
Turinys Srauto abstrakcija Javoje Bazinių klasių ypatybės Specializuoti srautai Srautai-filtrai. Dekoratoriaus šablonas. Objektų srautas. Serializacija. Taikymai, pagalbinės klasės.
Srauto abstrakcija Pagal: (SUN) Java Tutorials: Basic I/O
Java srautas Suprantamas kaip duomenų (baitų, simbolių) seka. Įgalina operuoti srauto skaitymo / rašymo operacijomis nepriklausomai nuo konkretaus įrenginio. Kiekvieną konkretaus tipo srautą atitinka konkrečios Java klasės objektas. java.io pagrindinės srautų klasės. java klasės paruoštos plėtimui.
Srautų tipai Baitų / simbolių srautai Skaitymo / rašymo srautai 4 bazinės klasės: InputStream, OutputStream operuoja baitais (byte tipas) Reader, Writer operuoja simboliais (char tipas), leidžia išvengti simbolių kodavimo / dekodavimo problemų Galima operuoti simboliais virš baitų srauto.
Baitų kopijavimo pavyzdys import java.io.*; public class CopyBytesPP{ public static void main(string[] args) throws IOException { InputStream in = new FileInputStream("orig.txt"); OutputStream out = new FileOutputStream("copy.txt"); for (int c; (c = in. read() )!= -1;) { out. write (c); } in.close(); out.close(); }}
Baitų kopijavimas (2)
public: Bazinė išvedimo klasė class OutputStream (Writer simboliams) Pagrindinė operacija išvesti baitą (simbolį) OutputStream() void close() void flush() void write(byte[] b) void write(byte[] b, int off, int len) abstract void write(int b)
Specializuotos išvedimo klasės įgalina atlikti specializuotas išvestis, parūpina papildomą funkcionalumą ByteArrayOutputStream, FileOutputStream, FilterOutputStream, ObjectOutputStream, PipedOutputStream BufferedWriter, CharArrayWriter, FilterWriter, OutputStreamWriter, PipedWriter, PrintWriter, StringWriter
Bazinėįvedimo klasė class InputStream (Reader- simboliams) public: void close() abstract int read() int read (byte[] b) int read (byte[] b, int off, int len) <kiti metodai>
Specializuotos įvedimo klasės įgalina skaityti iš specializuotų šaltinių, parūpina papildomą funkcionalumą ByteArrayInputStream, FileInputStream, FilterInputStream, InputStream, ObjectInputStream, PipedInputStream, SequenceInputStream, StringBufferInputStream BufferedReader, CharArrayReader, FilterReader, InputStreamReader, PipedReader, StringReader
Specializuotų srautų panaudojimas Sukuriamas reikiamas srauto objektas Pasinaudojama papildomomis galimybėmis. Pvz.: new ByteArrayInputStream(new byte[]{1,2,3}); new SequenceInputStream ( new FileInputStream( a.xx1 ), new FileInputStream( a.xx2 ) ); (new CharArrayWriter())... tochararray();
Bazinės I/O klasės išplėtimas Tiesioginis būdas sukurti savo I/O-klasę. Paveldint klasę iš Input/Output-Stream Užklojant metodą read() / write() Jeigu reikia užklojant ir kitus metodus Sekančioje skaidrėje pateiktas įvedimo srauto pavyzdys, kuris cikliškai gražina numatytąjį skaičių simbolių 0..9 kodų. Galėtų praversti testuojant modulius su I/O operacijomis.
import java.io.*; /** "Stream" as sequence of 1000 bytes as digits: 01234567890123456789... */ public class InputStream09 extends InputStream { static final int NMAX = 1000; int nread = 0; // How many bytes read public InputStream09() {super();} public int read () throws IOException { if (nread < NMAX){ int creturn = '0' + nread++ % 10; return creturn; //>>>> OK } else if (nread == NMAX) { nread++; return -1; //>>>> EOF } else throw new IOException("EOF or closed"); } public void close() throws IOException { nread= NMAX+1; // Mark file as closed super.close(); }}
public class TestInputStream09 { public static void main(string[] args) throws IOException { InputStream input =null; try { input = new InputStream09 (); for ( int b; (b = input.read())!= -1; ) { System.out.print((char)b); } input.close(); } catch ( IOException e ){ System.out.println(e); } finally { if (null!= input) {input.close();} } } }
Srautai kaip filtrai Remiasi realaus srauto apgaubimo (wrap) virtualaus srauto objektu filtru- idėja. Filtras prideda srautui papildomų funkcinių galimybių. Pvz., BufferedInputStream moka buferizuoti įvedamus baitus, nuskaitant iš vidinio srauto (įrenginio), LineNumberOutputStream moka skaičiuoti nuskaitytas eilutes. Abu apjungus, galima gauti buferizuotą srautą, su gebėjimu nustatyti eilutės numerį - getlinenumber(); Bazinis filtras FilterInputStream išvedimo nemodifikuoja.
Srautų apjungimo pavyzdys new LineNumberInputStream ( new BufferedInputStream ( new FileInputStream ( fn.abc ) ) );
UML klasių diagrama - InputStream +read() FilterInputStream #in +read() :LineNumberInputStream #in :BufferedInputStream #in :FileInputStream +read() +getlinenumber() 1* #pos +read() 1* +read()
Nuosavo filtro sukūrimas Išvedame klasę iš Filter-Input/Output- Stream/Reader Apibrėžiame konstruktorių, priimantį bazinio tipo srautą, kurį reikia apgaubti, kreipdamiesi į atitinkamą super() op-ją. Užklojame metodų read()/write() šeimą, peradresuodami vykdymą vidiniam srautui su reikiamomis modifikacijomis.
Pavyzdys: šifruojantysis išvedimo srautas Kiekvienąįrašomą baitą b šifruosime invertuodami bitus (key ^ b), kur key duotasis raktas perduodamas konstruktoriuje; esminė užklotis: void write(int b) {super.write(b^key);} reikėtų atitinkamai užkloti ir kitus write metodus.
Filtro įgyvendinimas /** Filter stream: Simple encryption */ import java.io.*; public class EncryptedOutputStream extends FilterOutputStream { final int key; public EncryptedOutputStream(OutputStream out, int key) { super(out); this.key = key; } public void write(int ch) throws IOException { ch ^= key; super.write(ch); } //...Kiti write metodai... } // end EncryptedOutputStream
Dekoratoriaus projektavimo šablonas Nagrinėjamas filtras tipiškas dekoratoriaus proj. šablono pavyzdys Įgalina vietoje komplikuotos klasių hierarchijos dinamiškai suteikti objektams reikalingas ypatybes realizacijos esmė objektas apgaubia kitą tos pačios klasių hierarchijos objektą, modifikuodamas vidiniam objektui deleguojamų operacijų vykdymą.
Kiti reikšmingi srautai Piped-Input/Output-Stream įgalina panaudoti I/O srautus kaip kanalą PrintWriter, PrintStream turi print(*) metodų šeimą bei format(*) metodą, panašaus naudojimo kaip C kalboje: System.out.format( "%f, %1$+020.10f %n", Math.PI);
Binarinis I/O Filtrai DataInputStream, DataOutputStreamįgalina įvesti/išvesti visas primityviąsias reikšmes (int, byte...) bei simbolių eilutes (String tipo) binariniu pavidalu. Kiekvienai rašymo op-jai yra atitinkama skaitymo: readdouble() atitinka writedouble(double v) ir t.t.
Data input/output sąsaja įgalina duomenų saugojimą tarp seansų String datafile = "invoicedata"; double[] prices = { 19.99, 9.99, 15.99, 3.99, 4.99 }; int[] units = { 12, 8, 13, 29, 50 }; String[] descs = { "Java T-shirt", "Java Mug", "Duke Juggling Dolls", "Java Pin", "Java Key Chain" };
Įrašymas out = new DataOutputStream(new BufferedOutputStream(new FileOutputStream(dataFile))); out.writeint(prices.length); for(int i = 0;i < prices.length;i++){ out.writedouble(prices[i]); out.writeint(units[i]); out.writeutf(descs[i]); }
Nuskaitymas in = new DataInputStream(new BufferedInputStream(new FileInputStream(dataFile))); double price; int unit; String desc; int n = in.readint(); // How many items for (int i = 0; i < n; i++) { } price = in.readdouble(); unit = in.readint(); desc = in.readutf(); System.out.format("You ordered %d units of %s at $%.2f%n", unit, desc, price);
Objektų srautai ObjectInputStream, ObjectOutputStream. Operacijos: writeobject(), readobject() Įgalina įrašyti į srautą ir po to nuskaityti bet kokį objektą, kuris pažymėtas Serialize interfeisu.
Objekto serializacija: įrašymas FileOutputStream out = new FileOutputStream("objdata.ser"); ObjectOutputStream s = new ObjectOutputStream(out); s.writeobject(new Date()); s.flush(); s.close();
Objekto nuskaitymas iš srauto FileInputStream in = new FileInputStream("objdata.ser"); ObjectInputStream s = new ObjectInputStream(in); Date date= (Date)s.readObject(); System.out.println(date); s.close();
Serializacijos pritaikymas Daugelis standartinių klasių serializuojamos, bet kai kurios - ne (pvz., Thread) Klasės neserializuojamus laukus galima pažymėti raktažodžiu transient Klasė gali papildyti standartinius ser-jos veiksmus parūpindama metodus writeobject, readobject Klasė gali sukurti savo ser-jos protokolą pagal Externalizable interfeisą.
Standartiniai srautai System.in /.out /.err sukuriami automatiškai System.in baitų srautas, patartina naudoti kaip new InputStreamReader(System.in) System.out/.err PrintStream tipo, įgalina išvesti bet kokio tipo duomenis simbolių pavidalu println()įbaitų srautą, koduojant standartiniu sistemos kodavimu
Kitos klasės java.io.file apgaubia failo vardą. Turi failų atributų tikrinimo, sukūrimo / pašalinimo, katalogų peržiūros operacijas. java.io.randomaccessfile tiesioginės skaitymo / rašymo kreipties klasė. Leidžia skaitymo / rašymo / pozicionavimo operacijas.
S K A I D R I Ų P A B A I G A