Sunteți pe pagina 1din 9

Paradigme de Programare Laboratorul 5

Laboratorul 5
5.1. I/O

Sistemul Intrare/Ieire (I/O) oferit de Java este unul destul de voluminos, coninnd un numr mare de clase i interfee. Un motiv pentru aceste dimensiuni ale API-ului I/O este i faptul c Java definete 2 sisteme I/O complete: unul pentru lucrul cu bytes i unul pentru lucrul cu caractere. 5.1.1. Stream-urile Operaiile I/O realizate n Java sunt bazate pe stream-uri (fluxuri). Un stream este un obiect abstract care fie produce informaii, fie le consum. Stream-urile sunt conectate la dispozitive fizice de intrare/ieire. Dei aceste dispozitive pot diferi, comportamentul stream-urilor rmne acelai. De exemplu aceleai operaii pot fi folosite pentru a scrie un mesaj pe ecran sau ntr-un fiier. Ierarhiile de clase care implementeaz n Java stream-urile sunt definite n pachetul java.io. 5.1.2. Stream-uri de octei i stream-uri de caractere Stream-urile pe octei (byte streams) ofer o modalitate facil de a controla intrri i ieiri de octei, care pot fi utile la controlarea datelor binare, mai ales atunci cnd se lucreaz cu fiiere. Aceste stream-uri sunt implementate prin dou ierarhii de clase ce au la baz dou clase abstracte: InputStream i OutputStream. Stream-urile pe caractere (character streams), folosite pentru controlul ieirilor i intrrilor de caractere, folosesc coduri Unicode, putnd fi astfel folosite atunci cnd se dorete internaionalizarea aplicaiilor. n mare parte, funcionalitatea oferit de ierarhia de clase ce implementeaz stream-urile pe octei este oglindit n cea oferit de ierarhia stream-urilor pe caractere. Acestea din urm, sunt bazate tot pe stream-urile pe octei, fiind create doar pentru a oferi un control mai facil al informaiilor bazate pe caractere. Stream-urile pe caractere sunt implementate prin dou ierarhii de clase care au la baz dou clase abstracte: Reader i Writer. 5.1.3. Stream-uri predefinite Toate programele Java import automat pachetul java.lang n care este definit clasa System. Printre altele, aceast clas conine 3 variabile stream predefinite: in (InputStream), out (PrintStream), err (PrintStream).

Paradigme de Programare Laboratorul 5

Clas Byte Stream BufferedInputStream BufferedOutputStream ByteArrayInputStream ByteArrayOutputStrea m DataInputStream DataOutputStream FileInputStream FileOutputStream FilterInputStream FilterOutputStream ObjectInputStream ObjectOutputStream PipedInputStream PipedOutputStream PrintStream

Descriere Intrare/ieire cu buffer Scriere/citire n/dintr-un array de octei Scrierea/citire a tipurilor Java standard Scriere/citire n/din fiiere Scriere/citire cu filtru Pentru scriere/citire obiecte

Clas Character Descriere Stream BufferedReader Scriere/citire cu buffer BufferedWriter CharArrayReader CharArrayWriter FileReader FilerWriter FilterReader FilterWriter InputStreamReader OutputStreamWriter LineNumberReader PipedReader PipedWriter PrintWriter PushbackReader StringReader StringWriter

Scriere/citire n/din array de caractere Scriere/citire n/din fiiere

Scriere/citire cu filtru

Stream de intrare(ieire) ce convertete octei n caractere (caractere n octei) Stream de intrare ce numr liniile

PushbackInputStream

Output stream ce conine print() i println() Stream intrare ce permite returnarea Combinaie din 2 sau mai multe streamuri de intrare care vor fi citite succesiv

Stream ieire ce conine print() i println() Stream intrare ce permite returnarea caracterelor Pentru scriere/citire n string-uri

RandomAccessFile SequenceInputStream

Paradigme de Programare Laboratorul 5

5.2.

Fluxuri de octei

Iniial Java a oferit doar stream-urile pe octei, iar citirea de la consol de exemplu se putea face doar folosind aceste stream-uri. Pentru aceasta clasa InputStream ofer metoda read() n 3 forme:
int read() throws IOException int read(byte data[]) throws IOException int read(byte data[], int start, int max) throws IOException

Prima variant a metodei returneaz -1 atunci cnd este ntlnit sfritul stream-ului. Varianta a doua scrie octeii citii n array-ul dat pn cnd acesta se umple sau se ajunge la sfritul stream-ului de intrare. Returneaz numrul de octei citii sau -1 atunci cnd stream-ul a fost epuizat. A treia variant specific de la ce poziie se scrie n array precum i numrul maxim de valori ce vor fi scrise. Observm c toate aceste metode pot genera o excepie de tipul IOException. Exemplu de citire a unui array de octei:
import java.io.*; class ReadBytes { public static void main(String args[]) throws IOException { byte data[] = new byte[10]; System.out.ptinln("Introduceti caractere: "); System.in.read(data); System.out.print("Ati introdus: "); for (int i=0; i < data.length; i++) { System.out.print((char) data[i]); } } }

Observm c ieirea la consol se face cu ajutorul metodelor print() i println() definite n clasa PrintStream. 5.2.1. Controlul fiierelor Pentru lucrul cu fiiere folosind stream-uri pe octei se folosesc clasele FileInputStream i FileOutputStream. Crearea unui stream de citire dintr-un fiier presupune crearea unui obiect de tipul FileInputStream. Cel mai folosit constructor este urmtorul:
FileInputStream(String numeFisier) throws FileNotFoundException

Citirea octeilor din fiier se poate face apoi folosind metoda read() care citete cte un octet pn cnd ajunge la sfrit i returneaz valoarea -1. Exemplu citire i afiare coninut fiier text:

Paradigme de Programare Laboratorul 5


import java.io.*; class CitesteFisier { public static void main(String args[]) throws IOException { int i; FileInputStream fin; try { fin = new FileInputStream(args[0]); } catch (FileNotFounsException ex) { System.out.println(fisierul nu exista); return; } catch (ArrayIndexOutOfBoundsException ex) { System.out.println(folosire: CitesteFisier <nume fisier>); return; } do { i = fin.read(); if (i != -1) System.out.println((char) i); } while(i != -1); fin.close(); } }

n mod similar, scrierea ntr-un fiier se poate face cu ajutorul metodei write(). 5.2.2. Scrierea i citirea datelor binare Pentru a scrie sau citi valori binare ale tipurilor primitive (cum ar fi int, double sau short), se folosesc clasele DataInputStream i DataOutputStream. DataOutputStream implementeaz interfaa DataOutput care definete metode pentru a scrie ntr-un stream toate toate tipurile primitive din Java: writeBoolean, writeByte n mod analog DataInputStream implementeaz interfaa DataInput ce definete metode pentru citirea valorilor primitive din stream-uri: readBoolean, readByte Exemplu de scriere i citire a valorilor binare:
import java.io; class ReadWriteBinaryData { public static void main(String args[]) throws IOException { DataOutputStream dataOut; DataInputStream dataIn; int i = 10; double d = 123.45; Boolean b = true; try { dataOut = new DataOutputStream(new FileOutputStream(test.txt)); } catch (IOException ex) { System.out.println(Fisierul nu poate fi accesat); return; } try { dataOut.writeInt(i); dataOut.writeDouble(d); dataOut.writeBoolean(b); } catch (IOException ex) {

Paradigme de Programare Laboratorul 5


System.out.println(Eroare la scriere in fisier); } dataOut.close(); try { dataIn = new DataInputStream(new FileInputStream(test.txt)); } catch(IOException ex) { System.out.println(Fisierul nu poate fi accesat); return; } try { i = dataIn.readInt(); d = dataIn.readDouble(); b = dataIn.readBoolean(); } catch (IOException ex) { System.out.println(Eroare la citire din fisier); } dataIn.close(); System.out.println(valorile citite: + i + + d + + b); } }

5.2.3. Accesul aleatoriu la coninutul fiierelor n exemplul anterior am accesat fiierul ntr-un mod secvenial, octet cu octet. Java permite ns i accesul n mod aleatoriu la coninutul unui fiier. Pentru aceasta se folosete clasa RandomAccesFile, care implementeaz interfeele DataInput i DataOutput. Constructorul acestei clase este urmtorul:
RandomAccessFile (String FileNotFoundException fileName, String accessType) throws

Pentru citire accessType este r iar pentru scriere i citire se folosete rw. Este oferit de asemenea i suport pentru poziionarea capului de citire la o anumit poziie:
void seek(int pos) throws IOException

5.3.

Fluxuri de caractere

Stream-urile pe octei sunt att puternice ct i flexibile. Totui nu sunt cele mai potrivite atunci cnd trebuie s lucrm cu caractere, motiv pentru care au fost create stream-urile pe caractere. 5.3.1. Citirea de la consol Am vzut anterior c stream-ul de intrare de la tastatur este System.in, care este un stream pe octei. Pentru a citi caractere vom folosi clasa InputStreamReader care convertete octeii n caractere, iar aceasta la rndul ei este de preferat s fie folosit ntr-un BufferedReader.
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));

Pentru a citi caractere se pot folosi variantele metodei read() oferita de BufferedReder:
int read() thows IOException; int read(char data[]) throws IOException; int read(char data[], int start, int max) throws IOException;

Paradigme de Programare Laboratorul 5 Pentru a citi string-uri se poate folosi metoda readLine(). 5.3.2. Scrierea la consol Dei se poate folosi System.out pentru a scrie mesaje la consol, se recomand folosirea clasei PrintWriter. Un constructor al acestei clase este urmtorul:
PrintWriter(OutputStream outputStream, boolean flush)

Parametrul boolean specific dac buffer-ul stream-ului este eliberat de fiecare dat cnd se face un apel la metoda println(). Metodele print() i println() oferite de PrintWriter suport toate tipurile, inclusiv Object. Pentru a scrie mesaje la consol se poate folosi o astfel de instan:
PrintWriter pw = new PrintWriter(System.out, true)

5.3.3. Controlul fiierelor n general, pentru a lucra cu caractere asupra fiierelor se folosesc clasele FileReader i FileWriter. Cei mai comuni constructori ai clasei FileWriter:
FileWriter(String fileName) throws IOException FileWriter(String fileName, boolean append) throws IOException

Dac se dorete adugare de text la coninutul unui fiier, atunci parametrul append este true. Exemplu de folosire a clasei FileWriter:
import java.io.*; class test { public static void main(String args[]) throws IOException { FileWriter fw; BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); try { fw = new FileWriter(test.txt); } catch (IOException ex) { System.out.println(fisierul nu este accesibil); return; } System.io.println(Introduceti text: ); do { String str = br.readLine(); if (str.compareTo(END) == 0) break; fw.write(str); } while (true); fw.close(); } }

Paradigme de Programare Laboratorul 5

5.4.

Fluxuri pe obiecte i serializare

Stream-urile pe obiecte (Object Streams) suport operaii I/O cu obiecte. Obiectele care pot fi folosite n astfel de operaii sunt obiectele ale cror clase sunt marcate cu interfaa Serializable. Se folosesc clasele ObjectInputStream i ObjectOutputStream care implementeaz interfeele ObjectInput i ObjectOutput. Acestea la rndul lor sunt subinterfee ale interfeelor DataInput i DataOutput. Aceasta nseamn c metodele folosite pentru scrierea i citirea tipurilor primitive sunt accesibile i din aceste clase. Metodele folosite n cazul obiectelor sunt readObject() i writeObject().
BigDecimal bigvalue = new BigDecimal(123.45); ... ObjectOutputStream out = new ObjectOutputStream(new BufferedOutputStream(new FileOutputStream(fisier))); out.writeObject(bigValue); ObjectInputStream in = new ObjectInputStream(new BufferedInputStrea(new FileInputStream(fisier))); BifDecimal bigValue = (BifDecimal) in.readObject();

Dac se ntmpl ca metoda readObject() s nu returneze tipul ateptat i se ncearc totui convertirea rezultatului, se obine o excepie de tipul ClassNotFoundException. Metodele readObject i writeObject sunt uor de folosit, dar logica pe care o implementeaz este destul de sofisticat. Pentru un obiect care ncapsuleaz doar valori primitive, de/serializarea este simpl. Lucrurile se complic atunci cnd un obiect conine referine la alte obiecte, care la rndul lor pot conine referine la altele. n cazul unui astfel de obiect, metoda writeObject parcurge ntreaga reea de referine i scrie toate obiectele n stream-ul controlat. Astfel, un singur apel al metodei writeObject poate provoca un volum mare de date s fie scrise n stream. Clasele care nu implementeaz interfaa Serializable nu vor putea fi de/serializate. Interfaa Serializable nu conine nici o metoda i nici un cmp, servind doar la marcarea faptului c o clas poate fi serializat. Subtipurile unei clase serializabile sunt la rndul lor serializabile. Pentru ca o proprietate s nu fie inclus n procesul de serializare, aceasta trebuie s fie marcat folosind cuvntul transient. La deserializare, proprietile marcate cu transient se iniializeaz cu valoarea lor implicit. Cuvntul transient se aplic doar proprietilor, nu i metodelor. Clasele care necesit un control special n timpul de/serializrii trebuie s implementeze metodele urmtoare:
private void writeObject(ObjectOutputStream out) throws IOException

metod responsabil pentru scrierea strii obiectului astfel nct metoda corespondent readObject s poat s l reconstruiasc.

private void readObject(ObjectInputStream in) throws IOException

responsabil pentru citirea strii obiectului i reconstruirea acestuia.

Paradigme de Programare Laboratorul 5

5.5.

Lucrul cu fiiere ZIP

Fiierele zip sunt un format comun pentru fiiere arhiv. Fiierele JAR sunt similare dar sunt specifice tehnologiei Java (conin un fiier manifest prin care se descrie coninutul ). Java ofer suport pentru accesul la coninutul fiierelor zip. Clasele ajuttoare se afl n pachetul java.util.zip: ZipEntry, ZipFile, ZipInputStream, ZipOutputStream, iar pentru excepii ZipException. Clasa ZipFile are 3 constructori:
ZipFile(File file) ZipFile(File file, int mode) ZipFile(String name)

Primele dou forme primesc un obiect de tip File, iar a treia form accept numele fiierului. Modurile de deschidere sunt date de constantele OPEN_READ (implicit) i OPEN_DELETE. Odat instaniat un obiect de acest tip se poate obine o list a intrrilor n arhiv. Acestea sunt returnate ntro enumeraie de valori ZipEntry. O intrare se poate obine i direct folosind numele ei: getEntry(String name).
import java.io.*; import java.util.*; import java.util.zip.*; public class ListZip { public static void main(String args[]) { for (int i=0, n=args.length; i<n; i++) { String name = args[i]; try { ZipFile zipfile = new ZipFile(name); Enumeration enum = zipfile.entries(); while (enum.hasMoreElements()) { ZipEntry entry = (ZipEntry)enum.nextElement(); System.out.println( entry.getName() + " / " + entry.getSize() + " / " + entry.getCompressedSize() ); } } catch (IOException e) { System.err.println("Error accessing: " + name); } } } }

Un obiect ZipEnty nu ofer acces direct la coninutul intrrii respective din arhiv, ci ofer doar informaii despre aceasta. Pentru a obine acces la stream-ul de intrare asociat, se folosete metoda oferit de ZipFile: getInputStream(ZipEntry entry). Exemplu urmtorul extrage un anumit fiier dintr-o arhiv: primul argument este fiierul zip, al doilea este numele intrrii, iar al treilea este numele fiierului extras.

Paradigme de Programare Laboratorul 5


import java.io.*; import java.util.*; import java.util.zip.*; public class GetFile { public static void main(String args[]) { if (args.length != 3) { System.err.println("Usage: java GetFile foo.zip name output"); } String zipname = args[0]; String entryname = args[1]; String output = args[2]; System.out.println("Copying " + entryname + " from " + zipname + " into " + output); try { ZipFile zipfile = new ZipFile(zipname); ZipEntry entry = zipfile.getEntry(entryname); InputStream is = zipfile.getInputStream(entry); OutputStream os = new FileOutputStream(output); byte array[] = new byte[512]; int length; while ((length = is.read(array)) != -1) { os.write(array, 0, length); } is.close(); os.close(); } catch (IOException e) { System.err.println("Error copying: " + zipname); } } }

5.6.

Tem

1. Testai exemplele din laborator. 2. Realizai o aplicaie care s permit salvarea unei liste de cri n 3 formate diferite: text, obiecte serializate (binar) i fiier arhivat (arhiv - binar). De asemenea, n funcie de extensia fiierului citit de la tastatur, se vor citi i afia crile din respectivul fiier (text, binar sau arhiv). Aplicaia trebuie s trateze toate situaiile/erorile ce pot s apar la rularea programului (de ex.: numele fiierului introdus este invalid, fiierul citit este corupt, etc.) Pentru implementare se poate folosi programul realizat n cadrul Laboratorului 2. Exemplu de fiier n format text:
Id: 123 Autor: Charles Dickens Titlu: Great Expectations ISBN: 0141439564 Editura: Penguin Classics AnAparitie: 2002 Id: 124 Autor: Jane Austen Titlu: Pride and Prejudice ISBN: 0553213105 Editura: Bantam Classics AnAparitie: 1983

S-ar putea să vă placă și