Sunteți pe pagina 1din 50

Cuvinte importante:

-tipuri de fluxuri de intrare/iesire Java: fluxuri de octeti, fluxuri de caractere; System.in, System.out, System.err; fluxuri-filtre; - fluxuri de octeti si clase predefinite Java utilizate: fluxuri nefiltrate de intrare care folosesc ca sursa un fiser; fluxuri nefiltrate de iesire care folosesc ca destinatie un fisier; - filtrarea fluxurilor de octeti si clase predefinite Java utilizate: zona tampon (buffer); fluxuri de intrare cu o zona tampon; fluxuri de iesire cu o zona tampon; fluxuri filtrate cu date de tipuri primitive; fluxuri filtrate cu date formatate; - fluxuri de caractere si clase predefinite Java utilizate: fluxuri nefiltrate de intrare care folosesc ca sursa un fisier; fluxuri filtrate de intrare cu o zona tampon; fluxuri filtrate de intrare cu o zona tampon care tin evidenta numerelor de linie.

3/2/2014

Tipuri de fluxuri de intrare/iesire Java


Toate datele din Java sunt scrise sau citite folosind fluxuri.
Un flux (stream) reprezinta o succesiune de octeti (bytes) sau de caractere transportat de la sau catre memoria RAM in care se afla programul Java. Un flux de intrare transporta datele de la o sursa externa (tastatura, fisier pe harddisc etc) catre programul Java. Un flux de iesire transporta datele din programul Java catre o destinatie externa (ecranul calculatorului, fisier pe hard-disc etc). Fluxurile de intrare/iesire in Java sunt create si manevrate cu ajutorul claselor din pachetul predefinit java.io. Din acest motiv orice program care executa operatii de intrare/iesire trebuie sa includa instructiunea: import java.io.*; Numarul claselor si a metodelor lor, definite in pachetul java.io, este foarte mare. De aceea se recomanda programatorului sa consulte in permanenta documentatia ce insoteste versiunea de Java folosita. In aceasta lectie vom descrie doar cateva clase Java care sunt folosite mai des pentru fluxuri de octeti si de caractere.
3/2/2014 2

Java foloseste doua tipuri principale de fluxuri:

- fluxuri de octeti;
- fluxuri de caractere. Fluxurile de octeti pot pastra valori intregi din domeniul 0 - 255. In acest format pot fi reprezentate o multitudine de date, cum ar fi: date numerice, programe executabile, comunicatii Internet sau cod Java (bytecode) etc. Generic, fluxurile de octeti sunt subclase ale claselor abstracte predefinite: - InputStream - pentru fluxuri de octeti de intrare si - OutputStream - pentru fluxuri de octeti de iesire.

Fluxurile de caractere reprezinta un tip special de flux de octeti, care se folosesc numai pentru date de tip text (tiparibile). Ele difera de fluxurile de octeti prin faptul ca setul de caractere Java suporta codificarea Unicode (cu doi octeti pe caracter).
Toate datele de tip text, cum ar fi fisierele text, paginile Web, sau alte formate de text, este necesar sa foloseasca fluxurile de caractere. Generic, fluxurile de caractere sunt subclase ale claselor abstracte predefinite: - Reader - pentru fluxuri de caractere de intrare si - Writer - pentru fluxuri de caractere de iesire.
3/2/2014 3

Java ofera trei fluxuri predefinite pentru operatii de I/O standard (de la tastatura, la ecranul calculatorului sau pentru erori) care sunt campuri ale clasei System inclusa in pachetul java.lang: - System.in - reprezinta intrarea standard (implicit, tastatura calculatorului); acest flux este de tip InputStream; - System.out - reprezinta iesirea standard (implicit, ecranul calculatorului); acest flux este de tip PrintStream; - System.err - reprezinta fluxul standard de iesire pentru mesaje de eroare (implicit, ecranul calculatorului); acest flux este de tip PrintStream. Dintre metodele clasei System, referitoare la fluxurile predefinite descrise mai sus, mentionam: - metoda setIn, care redirecteaza fluxul de intrare standard catre o alta sursa decat tastatura (de exemplu, un fisier pe disc); aceasta metoda are antetul: void setIn(InputStream <in>)

- metoda setOut, care redirecteaza fluxul de iesire standard catre o alta destinatie decat ecranul calculatorului (de exemplu, un fisier pe disc); aceasta metoda are antetul:
void setOut(PrintStream <out>)
3/2/2014 4

- metoda setErr, care redirecteaza fluxul de iesire standard al mesajelor de eroare catre o alta destinatie decat ecranul calculatorului (de exemplu, un fisier pe disc); aceasta metoda are antetul: void setErr(PrintStream <out>) Asocierea fluxului de intrare sau de iesire cu un filtru

Majoritatea claselor Java folosite in prezent permit realizarea de operatii de intrare/iesire mai performante prin asocierea fluxului cu un filtru, inainte de a citi sau scrie date.
Un filtru este un tip de flux care schimba modul in care se lucreaza cu un flux existent. Procedura de folosire a unui filtru pentru un flux presupune urmatorii pasi: 1. crearea (deschiderea) unui flux asociat cu sursa de date sau cu destinatia datelor; 2. crearea (deschiderea) unui flux de tip filtru asociat cu fluxul deschis la pasul 1; 3. citirea/scrierea datelor de la /in filtru si nu direct in flux.
3/2/2014 5

Fluxuri de octeti si clase predefinite Java utilizate

A. Fluxuri nefiltrate de octeti si clase predefinite utilizate


In schema de mai jos se prezinta doar o parte a structurii de clase ce poate fi folosita in operatiile cu fluxuri de intrare si iesire nefiltrate. Object InputStream OutputStream FileOutputStream

FileInputStream

Clasa InputStream este o clasa abstracta si din ea deriveaza toate celelalte clase care creaza fluxuri de octeti de intrare si realizeaza operatii de intrare pe aceste fluxuri. Clasa OutputStream este o clasa abstracta si din ea deriveaza toate celelalte clase care creaza fluxuri de octeti de iesire si realizeaza operatii de iesire pe aceste fluxuri. Nota: Deoarece fluxurile de intrare/iesire semnaleaza exceptia IOException la aparitia unei erori, toate operatiile legate de fluxuri se incadreaza in blocuri try catch, care sa intercepteze aceasta exceptie.
3/2/2014 6

Fluxuri nefiltrate de octeti de intrare care folosesc ca sursa un fisier Sunt folosite pentru transferul de date de la fisierele aflate pe hard-discuri, pe CDROM sau pe alte dispozitive de stocare (ce pot fi referite printr-o cale de director si un nume) catre aplicatia Java. Crearea (deschiderea) unui flux de intrare de la un fisier se realizeaza cu ajutorul constructorului clasei FileInputStream, care are forma: FileInputStream(String <sir>) unde: - <sir> - reprezinta numele, si eventual calea, fisierului; la specificarea caii fisierului trebuie sa se foloseasca doua caractere backslash pentru a nu se confunda cu o secventa escape. Daca fisierul nu poate fi deschis, atunci este lansata exceptia FileNotFoundException. De exemplu, urmatoarea instructiune deschide un flux de intrare de la fisierul test.dat: FileInputStream fis = new FileInputStream(test.dat);
3/2/2014 7

Dupa deschiderea fluxului de intrare din fisier se pot folosi metodele acestui flux pentru realizarea diverselor operatii de intrare. Descriem cateva dintre ele. Metoda read() citeste un octet din fluxul de intrare; rezultatul intors este un intreg din intervalul 0 - 255. Daca s-a detectat sfarsitul de fisier, rezultatul intors este -1. Metoda read cu trei parametrii are forma: read (byte [] <b>, int <poz_ini>, int <lungime>) unde: - <b> - un tablou de octeti in care se vor memora datele citite; - <poz_ini> - pozitia elementului din cadrul tabloului unde se va stoca primul octet de date; - <lungime> - numarul de octeti care se vor citi din fluxul de intrare repetand metoda read fara parametri. Metoda returneaza un intreg care reprezinta numarul de octeti cititi sau -1 daca, de la inceput, fluxul de intrare este la sfarsitul sau. Metoda skip avanseaza cu n pozitii (octeti) in fluxul de intrare, nedepasind bineinteles sfarsitul fluxului. Rezultatul intors de metoda este numarul de pozitii peste care s-a trecut efectiv.
3/2/2014 8

Metoda skip are forma:

skip(long <n>)
unde : <n> - nr de octeti sariti in fluxul de intrare. Metoda available() este folosita pentru a returna numarul de octeti ce mai pot fi cititi la momentul curent din fluxul de intrare. Metoda close() inchide fluxul de intrare respectiv si elibereaza resursele sistem asociate cu acesta. De exemplu, programul CitesteFiserOcteti .java citeste octeti dintr-un flux de intrare al unui fisir cu numele test.doc. Dupa citirea ultimului octet din fisier, pentru inchiderea fluxului de intrare se foloseste metoda close(). Aceasta operatie trebuie realizata pentru a elibera resursele sistemului asociate fisierului deschis. Fisierul de intrare cu numele test.dat din care se citesc date in forma binara contine doua linii: 0123456789 Ionescu Florin Acest fisier a fost creat cu utilitarul Notepad.
3/2/2014 9

import java.io.*; public class CitesteFisierOcteti { public static void main(String [] args) { try { FileInputStream fis = new FileInputStream("test.dat"); int index = 0; int octet = fis.read(); while (octet != -1) { System.out.print(octet + " "); index++; octet = fis.read(); } fis.close(); System.out.println("\nOcteti cititi: " + index); } catch (IOException e) { System.out.println("Eroare - " + e.getMessage()); } } }
3/2/2014 10

Dupa executia programului va fi afisat fiecare octet din fisierul test.dat, urmat de numarul total de octeti cititi, ca mai jos: 48 49 50 51 52 53 54 55 56 57 13 10 73 111 110 101 115 99 117 32 70 108 111 114 105 110 Octeti cititi: 26 Observatie: Se observa ca valorile octetilor afisati sunt codurile ASCII ale caracterelor din cele doua linii existente in fisier. Fluxuri nefiltrate de octeti de iesire care folosesc ca destinatie un fisier Sunt folosite pentru transferul de date de la aplicatia Java catre fisierele aflate pe hard-discuri, pe CD-ROM sau pe alte dispozitive de stocare (ce pot fi referite printro cale de director si un nume). Crearea (deschiderea) unui flux de iesire catre un fisier se realizeaza cu ajutorul constructorului clasei FileOutputStream, care are forma: FileOutputStream(String <sir>)

unde:
- <sir> - reprezinta numele, si eventual calea, fisierului; la specificarea caii fisierului trebuie sa se foloseasca doua caractere backslash pentru a nu se confunda cu o secventa escape.
3/2/2014 11

Trebuie sa se aiba o grija deosebita atunci cand se specifica numele fisierului in care se scrie. Daca se foloseste numele unui fisier deja existent, odata cu inceperea scrierii datelor, acesta va fi sters definitiv.
Constructorul cu doi parametrii are forma: FileOutputStream(String <sir>, boolean <adauga>) unde: - <sir> - reprezinta numele, si eventual calea, fisierului; la specificarea caii fisierului trebuie sa se foloseasca doua caractere backslash pentru a nu se confunda cu o secventa escape.

- <adauga> - poate avea valoare true, caz in care se face adaugarea datelor la sfarsitul fisierului, sau poate avea valoarea false, caz in care nu se face adaugarea de date la sfarsitul fisierului ci suprascrierea datele existente; daca fisierul nu poate fi deschis, atunci este lansata exceptia FileNotFoundException.
De exemplu, urmatoarea instructiune deschide un flux de iesire catre fisierul test1.dat: FileOutputStream fis = new FileOutStream(test1.dat);
3/2/2014 12

Urmatoarea instructiune deschide un flux de iesire catre fisierul test1.dat pentru a adauga octeti la sfarsitul fisierului: FileOutputStream fis = new FileOutStream(test1.dat, true); Dupa deschiderea fluxului de iesire din fisier se pot folosi metodele acestui flux pentru realizarea diverselor operatii de iesire. Descriem cateva dintre ele.

Metoda write cu un parametru scrie un octet in fluxul de iesire. Aceasta metoda are forma:
write(int <b>) unde: <b> - variabila care contine octetul de scris in fluxul de iesire.

Metoda write cu doi parametrii scrie un tablou de octeti in fluxul de iesire si are forma:
write (byte [] <b>) unde: - <b> - specifica un tablou de octeti care va fi scris in fluxul de iesire; in fisier vor fi scrisi b.length octeti.
13

3/2/2014

Metoda write cu trei parametrii are forma: write (byte [] <b>, int <poz_ini>, int <lungime>) unde:

- <b> - specifica un tablou de octeti care va fi scris in fluxul de iesire;


- <poz_ini> - pozitia elementului din cadrul tabloului de la care se incepe scrierea in fluxul de iesire; - <lungime> - numarul de octeti care se vor scrie in fluxul de iesire. Metoda close() inchide fluxul de iesire respectiv. Programul urmator (ScrieFisierOcteti.java) scrie un tablou de octeti intr-un flux de iesire intr-un fisier date cu numele test1.gif. Dupa scrierea ultimului octet in fisier, pentru inchiderea fluxului de iesire se foloseste metoda close(). Aceasta operatie trebuie realizata pentru a elibera resursele sistemului asociate fisierului deschis.

3/2/2014

14

import java.io.*; public class ScrieFisierOcteti { public static void main (String [] args) { int [] octeti = { 71, 73, 70, 56, 57, 97, 15, 0, 15, 0, 128, 0, 0, 111, 111, 111, 0, 0, 0, 44, 0, 0, 0, 0, 15, 0, 15, 0, 0, 2, 33, 132, 127, 161, 200, 185, 205, 84, 128, 241, 81, 35, 175, 155, 26, 228, 25, 105, 33, 102, 0, 165, 201, 145, 169, 154, 142, 112, 0, 200, 200, 0, 200, 200, 200, 200 } ; try { FileOutputStream fis = new FileOutputStream("test1.gif"); for (int i = 0; i < octeti.length; i++) fis.write(octeti[i]); fis.close(); } catch(IOException e) { System.out.println("Eroare - " + e.getMessage()); } } }
3/2/2014 15

B. Filtrarea fluxurilor de octeti si clase predefinite Java utilizate


Fluxurile filtrate sunt fluxuri care selecteaza si, astfel, modifica informatia transmisa printr-un flux existent (de tip InputStream sau OutputStream). Acestea sunt create folosind subclase ale claselor FilterInputStream si FilterOutputStream.
Fluxurile FilterInputStream si FilterOutputStream nu realizeaza in mod direct nici un fel de operatie de filtrare. Dar, din ele deriveaza subclase (de exemplu, BufferedInputStream) care sunt folosite pentru anumite tipuri de filtrari. In schema de mai jos se prezinta doar o parte a structurii de clase ce poate fi folosita in operatiile cu fluxuri de intrare si iesire filtrate. Object

InputStream FilterInputStream

OutputStream FilterOutputStream DataOutputStream

BufferedInputStream DataInputStream BufferedOutputStream

PrintStream
3/2/2014 16

B.1 Fluxuri de octeti cu o zona tampon (buffer) Un tampon (buffer) reprezinta o zona de memorie RAM in care se pot pastra date din fluxul de intrare sau de iesire pana la momentul citirii sau scrierii lor intr-o aplicatie Java. Prin folosirea unui tampon se pot accesa (citi sau scrie) date fara a folosi sursa originala (fisierul) sau destinatia originala (fisierul) de date. Zona tampon este folosita ca o zona intermediara pentru citirea/ scrierea datelor din/in fluxul de intrare/iesire. Pentru memoria tampon se mai foloseste si termenul de memorie de lucru. Aceasta tehnica este mai eficienta intrucat utilizarea zonei tampon evita accesarea fisierului pentru fiecare citire/scriere, in acest mod micsorandu-se timpul de lucru al aplicatiei Java. Nota: Deoarece fluxurile de intrare/iesire cu tampon semnaleaza exceptia IOException la aparitia unei erori, toate operatiile legate de fluxuri se incadreaza in blocuri try catch, care sa intercepteze aceasta exceptie. Fluxuri de octeti de intrare cu o zona tampon

Un flux de intrare cu tampon poseda un tampon cu date din care se face citirea. Cand aplicatia Java citeste date, acestea sunt cautate mai intai in zona tampon si apoi in sursa originala de intrare. Fluxurile de octeti de intrare cu tampon folosesc clasa BufferedInputStream.
3/2/2014 17

Crearea (deschiderea) unui flux de intrare cu tampon se realizeaza cu ajutorul constructorilor clasei BufferedInputStream. Cand este deschis un flux de intrare cu tampon se creaza si o zona tampon, sub forma unui tablou de octeti, atasata acestuia. Constructorii clasei BufferedInputStream au una din formele: a)

BufferedInputStream(InputStream <in>)
unde: - <in> - reprezinta fluxul original de tip InputStream. Nota: Zona tampon are o lungime care este aleasa implicit (automat). b) BufferedInputStream(InputStream <in>, int <lg_buffer>) unde:

- <in> - reprezinta fluxul original de tip InputStream;


- <lg_buffer> - reprezinta lungimea zonei tampon a fluxului de intare.
18

3/2/2014

Dupa deschiderea fluxului de intrare cu tampon se pot folosi metodele acestui flux pentru realizarea diverselor operatii de intrare. Descriem cateva dintre ele.
Metoda read() citeste un octet din fluxul de intrare cu tampon; rezultatul intors este un intreg din intervalul 0 - 255. Daca s-a detectat sfarsitul de fisier, rezultatul intors este -1. Metoda read cu trei parametrii are forma: read (byte [] <b>, int <poz_ini>, int <lungime>) unde: - <b> - un tablou de octeti in care se vor memora datele citite; - <poz_ini> - pozitia elementului din cadrul tabloului unde se va stoca primul octet de date; - <lungime> - numarul de octeti care se vor citi din fluxul de intrare cu tampon repetand metoda read fara parametri. Metoda returneaza un intreg care reprezinta numarul de octeti cititi sau -1 daca, de la inceput, fluxul de intrare este la sfarsitul sau.
3/2/2014 19

Metoda skip avanseaza cu n pozitii (octeti) in fluxul de intrare cu tampon si descarca n octeti din flux, nedepasind, bineinteles, sfarsitul fluxului. Rezultatul intors de metoda este numarul de pozitii peste care s-a trecut efectiv.
Metoda skip are forma: skip(long <n>) unde : <n> - nr de octeti sariti in fluxul de intrare si descarcati din fluxul de intare. Metoda available() este folosita pentru a returna numarul de octeti ce mai pot fi cititi la momentul curent atat din zona tampon, cat si din fluxul de intrare. Metoda close() inchide fluxul de intrare cu tampon si elibereaza resursele sistem asociate cu acesta. Fluxuri de octeti de iesire cu o zona tampon Un flux de iesire cu tampon poseda un tampon cu date care nu au fost inca scrise in destinatia originala a fluxului. Atunci cand datele sunt directionate intr-un flux de iesire cu tampon, continutul acestuia nu va fi transmis catre destinatie decat dupa ce zona tampon atasata s-a umplut. Fluxurile de octeti de iesire cu tampon folosesc clasa BufferedOutputStream.
3/2/2014 20

Crearea (deschiderea) unui flux de iesire cu tampon se realizeaza cu ajutorul constructorilor clasei BufferedOutputStream. Cand este deschis un flux de iesire cu tampon se creaza si o zona tampon, sub forma unui tablou de octeti, atasata acestuia. Constructorii clasei BufferedOutputStream au una din formele: a)

BufferedOuputStream(OutputStream <out>)
unde: - <out> - reprezinta fluxul de iesire de tip OutputStream. Nota: Zona tampon are o lungime care este aleasa implicit (automat). b) BufferedOutputStream(OutputStream <out>, int <lg_buffer>) unde:

- <out> - reprezinta fluxul de iesire de tip OutputStream;


- <lg_buffer> - reprezinta lungimea zonei tampon a fluxului de iesire.
21

3/2/2014

Dupa deschiderea fluxului de iesire cu tampon se pot folosi metodele acestui flux pentru realizarea diverselor operatii de iesire. Descriem cateva dintre ele. Metoda write cu un parametru scrie un octet in fluxul de iesire cu tampon. Aceasta metoda are forma: write(int <b>)

unde: <b> - variabila care contine octetul de scris in fluxul de iesire cu tampon; valoarea acestei variabile trebuie sa apartina intervalului 0 - 255; daca se incearca scrierea unei valori care este mai mare decat 255 va fi stocat numai restul impartirii acestei valori la 256.
Metoda write cu trei parametrii are forma: write (byte [] <b>, int <poz_ini>, int <lungime>) unde: - <b> - specifica un tablou de octeti care va fi scris in fluxul de iesire cu tampon;

- <poz_ini> - pozitia elementului din cadrul tabloului de la care se incepe scrierea in fluxul de iesire cu tampon;
- <lungime> - numarul de octeti care se vor scrie in fluxul de iesire cu tampon.
3/2/2014 22

Metoda flush() transmite (scrie) continutul zonei tampon la destinatia fluxului de iesire original chiar daca aceasta zona tampon nu s-a umplut inca. Cu ajutorul acestei metode se realizeaza golirea zonei tampon chiar daca aceasta nu s-a umplut inca. Metoda close() inchide fluxul de iesire cu tampon si elibereaza resursele sistem asociate cu acesta. Urmatorul program (IOBinarTampon.java) scrie o serie de octeti intr-un flux de iesire cu tampon asociat cu un fisier pe disc. Limita inferioara si limita superioara din seria de numere sunt specificate in doua argumente transmise prin linia de comanda, ca in exemplul urmator: java IOBinarTampon 2 30 Daca nu se transmit argumente prin linia de comanda, implicit limita inferioara este 0 iar limita superioara este 255.

Dupa scrierea in fisier, programul deschide un flux de intrare cu tampon si citeste octetii scrisi in fisier.

3/2/2014

23

import java.io.*; public class IOBinarTampon { public static void main (String [] args) { int limInf = 0; int limSup = 255; try { if (args.length > 1) { limInf = Integer.parseInt(args[0]); limSup = Integer.parseInt(args[1]); } else if(args.length > 0) limInf = Integer.parseInt(args[0]); FluxOcteti fo = new FluxOcteti(limInf, limSup); System.out.println("\nScrie: "); boolean succesScrie = fo.scrieFlux(); System.out.println("\nCiteste: "); boolean succesCiteste = fo.citesteFlux(); } catch(NumberFormatException nfe) { System.out.println("Eroare: " + "Nu ati introdus un numar intreg"); } } }
3/2/2014 24

class FluxOcteti { private int inceput = 0; private int sfarsit = 255; public FluxOcteti(int inceput, int sfarsit) { this.inceput = inceput; this.sfarsit = sfarsit; } boolean scrieFlux() { try { BufferedOutputStream fluxTampon = new BufferedOutputStream( new FileOutputStream("numere.dat")); for (int i = inceput; i <= sfarsit; i++) { fluxTampon.write(i); System.out.print(" " + i); } fluxTampon.close(); return true; } catch(IOException e) { System.out.print("Eroare: " + e.getMessage()); return false; } }
3/2/2014 25

boolean citesteFlux() { try { BufferedInputStream fluxTampon = new BufferedInputStream( new FileInputStream("numere.dat")); int i = 0; do { i = fluxTampon.read(); if (i != -1) System.out.print(" " + i); } while (i != -1); fluxTampon.close(); return true; } catch(IOException e) { System.out.print("Eroare: " + e.getMessage()); return false; } }
}

3/2/2014

26

Observatie: Aplicatia Java prezentata mai sus poate primi unul sau doua argumente atunci cand este lansata. Modul de transmitere a unor argumente la aplicatii Java depinde de platforma pe care se executa Java. In Windows si Unix se pot transmite argumente prin intermediul liniei de comanda.

Argumentele trebuie adaugate la executie dupa numele programului si daca sunt mai multe decat unul, atunci argumentele sunt separate prin spatii.
In cadrul aplicatiei Java, argumentele din linia de comanda sunt preluate de metoda main() sub forma unui tablou de siruri:

public static void main(String [] args) { //corpul metodei }


Argumentele din linia de comanda sunt stocate in tabloul de siruri de caractere incepand cu primul element din tablou (care are indexul 0). Deci, in tabloul de siruri de caractere al metodei main() nu se preia si numele programului ca la C/C++.

3/2/2014

27

B2. Fluxuri filtrate cu date de tipuri primitive Clasele DataInputStream si DataOutputStream ofera, ca facilitate suplimentara, posibilitatea ca fluxurile sa nu mai fie privite strict la nivel de octet, ci ca succesiuni de date primitive. Prin aceasta, datele vor fi scrise in fluxul de iesire intr-un format independent de modul de reprezentare al datelor in sistemul pe care se lucreaza. Constructorul clasei DataInputStream creaza un nou flux de intrare ce suprapune pe cel existent primit ca argument. Constructorul are forma: DataInputStream(InputStream <in>) unde:

- <in> - specifica fluxul de intrare existent, de exemplu, un flux de intrare cu tampon sau un flux de intrare din fisier.

Constructorul clasei DataOutputStream creaza un nou flux de iesire ce suprapune pe cel existent primit ca argument. Constructorul are forma:
DataOutputStream(OutputStream <out>) unde:

- <out> - specifica fluxul de iesire existent, de exemplu, un flux de iesire cu tampon sau un flux de iesire in fisier. Deoarece fluxurile filtrate de intrare/iesire cu date de tipuri primitive semnaleaza exceptia IOException la aparitia unei erori, toate operatiile legate de fluxuri se incadreaza in blocuri try catch, care sa intercepteze aceasta exceptie.
3/2/2014 28

Urmatoarea lista prezinta metodele de citire si de scriere ce pot fi folosite pentru fluxurile de tipul DataInputStream, si respectiv de tipul DataOutputStream: - readBoolean(); writeBoolean(boolean <v>); - readChar(); writeChar(char <v>); - readDouble(); writeDouble(double <v>);

- readFloat(); writeFloat(float <v>);


- readInt(); writeInt(int <v>); - readLong(); writeLong(long <v>); - readShort(); writeShort(short <v>); Fiecare dintre metodele de citire prezentate incearca sa citeasca un numar de octeti egal cu lungimea pe care sunt reprezentate tipurile respective indicate in numele metodei. De exemplu, metoda readBoolean() citeste un octet si returneaza true daca octetul citit este diferit de zero.

Fiecare dintre metodele de scriere prezentate incearca sa scrie un numar de octeti egal cu lungimea pe care sunt reprezentate tipurile respective indicate in numele metodei. De exemplu, metoda writeBoolean() scrie intr-un octet valoarea 1 sau valoarea 0, dupa cum parametrul <v> este true sau false.
3/2/2014 29

Observatii:
1. Datele citite folosind metodele clasei DataInputStream trebuie sa fi fost scrise in fisier cu metodele complementare ale clasei DataOutputStream. 2. Nu toate metodele de citire dintr-un flux de tip DataInputStream returneaza o valoare ce poate indica faptul ca s-a ajuns la sfarsitul fluxului. In astfel de cazuri se semnaleaza exceptia EOFException care indica faptul ca s-a ajuns la sfarsitul fluxului de intrare. Urmatorul program (IODataTampon.java) scrie o serie de valori de tip float intr-un flux de iesire DataOutputStream cu tampon asociat cu un fisier pe disc. Limita inferioara si limita superioara din seria de numere reale sunt specificate in doua argumente transmise prin linia de comanda, ca in exemplul urmator: java IOBinarTampon 2 30 Daca nu se transmit argumente prin linia de comanda, implicit limita inferioara este 0 iar limita superioara este 255. Dupa scrierea in fisier, programul deschide un flux de intrare cu tampon si citeste datele de tip float scrise in fisier.
3/2/2014 30

import java.io.*; public class IODataTampon { public static void main (String [] args) { float limInf = 0; float limSup = 255; try { if (args.length > 1) { limInf = Float.parseFloat(args[0]); limSup = Float.parseFloat(args[1]); } else if(args.length > 0) limInf = Float.parseFloat(args[0]); FluxDatePrimitive fd = new FluxDatePrimitive(limInf, limSup); boolean succesScrie = fd.scrieFlux(); System.out.println("\nCiteste: "); boolean succesCiteste = fd.citesteFlux(); } catch(NumberFormatException nfe) { System.out.println("Eroare: " + "Nu ati introdus un numar real"); } } }
3/2/2014 31

class FluxDatePrimitive { private float inceput = 0; private float sfarsit = 255; public FluxDatePrimitive(float inceput, float sfarsit) { this.inceput = inceput; this.sfarsit = sfarsit; } boolean scrieFlux() { try { DataOutputStream fluxDate = new DataOutputStream( new BufferedOutputStream(new FileOutputStream("numere.dat"))); for (float i = inceput; i <= sfarsit; i+=0.5) fluxDate.writeFloat(i); fluxDate.close(); return true; } catch(IOException e) { System.out.print("Eroare: " + e.getMessage()); return false; } }

3/2/2014

32

boolean citesteFlux() { try { DataInputStream fluxDate = new DataInputStream( new BufferedInputStream(new FileInputStream("numere.dat"))); float i = 0; try { while (true) { i = fluxDate.readFloat(); System.out.print(" " + i); } } catch(EOFException eof) { fluxDate.close(); } return true; } catch(IOException e) { System.out.print("Eroare: " + e.getMessage()); return false; } } }
3/2/2014 33

Aplicatia prezentata este un exemplu de suprapunere a mai multor filtre peste un flux original de tip FileInputStream. Fluxul filtrat este construit in trei etape: - se creaza un flux de iesire in fisier, asociat cu fisierul numere.dat; - se asocieaza fluxului de fisier un flux de iesire filtrat cu tampon;

- se asociaza fluxului de iesire cu tampon un flux de tip DataInputStream.


Instructiunea while(true) din metoda citesteFlux() creaza un ciclu infinit in aparenta, pentru ca la un moment dat va fi atins sfarsitul fluxului si va fi semnalata o exceptie EOFException. Metoda readFloat() citeste valorile intregi din flux.

B3. Fluxuri filtrate cu date formatate


Clasa PrintStream furnizeaza un flux filtru de iesire care permite afisarea de numere, valori boolean, String si alte tipuri de obiecte in format text. Filtrul de iesire PrintStream converteste numerele si alte tipuri de date la reprezentari text, inainte de transmiterea datelor la fluxul de iesire. De exemplu, atunci cand programul afiseaza valoarea intreaga 42, clasa PrintStream converteste numarul la caracterele 4 si 2 si apoi transmite caracterele mai departe in flux.

3/2/2014

34

In plus, fluxul PrintStream da posibilitatea (optional) de a goli automat zona tampon dupa ce a fost scris un tablou de octeti sau un octet egal cu \n. Metodele acestei clase nu semnaleaza niciodata exceptia IOException. Fluxul System.out, pe care l-am folosit aproape in toate lectiile de pana acum pentru afisarea mesajelor la ecranul calculatorului, este de fapt un flux de tip PrintStream. Prezentam doi dintre constructorii acestei clase: PrintStream(OutputStream <out>) PrintStream(OutputStream <out>, boolean <auto_golire>) unde: - <out> - specifica fluxul de iesire existent; <auto_golire> - specifica daca se goleste automat zona tampon dupa ce a fost scris un tablou de octeti sau un octet egal cu \n (daca valoarea este true).

3/2/2014

35

Mentionam cateva metode ale acestei clase: - print (String <s>) - print (char <c>) - print (boolean <b>) - print (char <c>) - print (int <i>) - print (long <l>) - print (float <f>) - print (double <d>) Pentru fiecare metoda print exista si perechea ei println, care adauga caracterul \n in fluxul de iesire.

In plus, exista si metoda println fara parametrii, care scrie doar caracterul de sfarsit de linie \n.
Metodele print si println scriu argumentul lor intr-un format de tip text si anume identic cu cel produs de apelurile metodei String.valueOf(x).

Un flux PrintStream nu are ca destinatie numai ecranul calculatorului ci orice destinatie de flux, inclusiv un fisier text ASCII. De exemplu, urmatoul program (PrintStreamFile.java) afiseaza un String, un intreg si un numar in virgula mobila intr-un fisier, print.txt.
3/2/2014 36

import java.io.*; public class PrintStreamFile { public static void main(String [] args) { double nr1 = 234.5; int nr2 = 120; try { PrintStream ps = new PrintStream(new FileOutputStream("print.txt")); ps.println ("Date pentru testarea fluxului PrintStream"); ps.print(nr1); ps.print(' '); ps.print(nr2); ps.println(); ps.println(Math.PI); ps.close(); } catch(IOException e) { System.out.println("Eroare la scrierea fisierului: " + e.getMessage()); } } }

3/2/2014

37

Fluxuri de caractere si clase predefinite Java utilizate


Fluxurile de caractere se folosesc pentru lucrul cu orice text reprezentat in format ASCII sau Unicode (set de caractere international care include si ASCII). Ele opereaza asupra sirurilor de caractere si tablourilor de caractere.
Exemple de fisiere cu care putem lucra prin intermediul fluxurilor de caractere sunt fisierele de text simplu, documentele HTML sau fisiere care contin cod sursa Java.

A. Fluxuri de caractere de intrare nefiltrate si filtrate


In schema de mai jos se prezinta doar o parte a structurii de clase ce poate fi folosita in operatiile cu fluxuri de caractere de intrare nefiltrate si filtrate. Object Reader

BufferedReader

InputStreamReader

LineNumberReader
3/2/2014

FileReader
38

Clasa Reader este o clasa abstracta si din ea deriveaza toate celelalte clase care creaza fluxuri de caractere de intrare si realizeaza operatii de intrare pe aceste fluxuri. Nota: Deoarece fluxurile de intrare semnaleaza exceptia IOException la aparitia unei erori, toate operatiile legate de fluxuri se incadreaza in blocuri try catch, care sa intercepteze aceasta exceptie. Este indicat sa folosim clasa Reader pentru lucru cu text si nu fluxuri de octeti. A.1 Fluxuri nefiltrate de caractere de intrare care folosesc ca sursa un fisier

Sunt folosite pentru transferul de date de la fisierele aflate pe hard-discuri, pe CDROM sau pe alte dispozitive de stocare (ce pot fi referite printr-o cale de director si un nume) catre aplicatia Java. Principala clasa folosita pentru citirea de fluxuri de caractere dintr-un fisier este FileReader. Aceasta clasa mosteneste clasa InputStreamReader, care citeste un flux de octeti si ii converteste in valori intregi corespunzatoare caracterelor Unicode.

3/2/2014

39

Crearea (deschiderea) unui flux de intrare de la un fisier se realizeaza cu ajutorul constructorului clasei FileReader, care are forma: FileReader(String <sir>) unde: - <sir> - reprezinta numele, si eventual calea, fisierului; la specificarea caii fisierului trebuie sa se foloseasca doua caractere backslash pentru a nu se confunda cu o secventa escape. Daca fisierul nu poate fi deschis, atunci este lansata exceptia FileNotFoundException. De exemplu, urmatoarea instructiune deschide un flux de intrare de la fisierul test.doc: FileReader document = new FileReader(test.doc);

3/2/2014

40

Dupa deschiderea fluxului de caractere de intrare din fisier se pot folosi metodele acestui flux pentru realizarea diverselor operatii de intrare. Descriem cateva dintre ele.
Metoda read() citeste un caracter din fluxul de intrare; rezultatul intors este un intreg din intervalul 0 - 65535. Daca s-a detectat sfarsitul de fisier, rezultatul intors este -1.

Metoda read cu trei parametrii are forma:


read (char [] <c>, int <poz_ini>, int <lungime>) unde: - <c> - un tablou de caractere in care se vor memora datele citite; - <poz_ini> - pozitia elementului din cadrul tabloului unde se va stoca primul caracter de date; - <lungime> - numarul de caractere care se vor citi din fluxul de intrare repetand metoda read fara parametri. Metoda returneaza un intreg care reprezinta numarul de caractere citite sau -1 daca, de la inceput, fluxul de intrare este la sfarsitul sau.
3/2/2014 41

Nota: Deoarece metoda read() a unui flux de caractere returneaza o valoare intreaga, trebuie sa se converteasca explicit prin cast aceasta valoare inainte de a o afisa sau de a o salva intr-un tablou de caractere. Fiecare caracter poseda un cod numeric care reprezinta pozitia sa in setul de caractere Unicode. Valoarea intreaga citita din flux reprezinta chiar acest cod numeric. Metoda skip avanseaza cu n pozitii (caractere) in fluxul de intrare, nedepasind bineinteles sfarsitul fluxului. Rezultatul intors de metoda este numarul de pozitii peste care s-a trecut efectiv. Metoda skip are forma: skip(long <n>)

unde :
<n> - nr de caractere sarite in fluxul de intrare. Metoda ready() specifica daca acest flux de caractere este disponibil pentru a fi citit. Un flux de caractere dintr-un fisier este disponibil pentru a fi citit daca zona tampon de intrare nu este goala (in caz ca ea exista) sau daca exista octeti disponibili de a fi cititi de la fluxul de octeti de tip InputStreamReader. Metoda close() inchide fluxul de intrare respectiv si elibereaza resursele sistem asociate cu acesta.
3/2/2014 42

A.2 Fluxuri filtrate de caractere de intrare cu o zona tampon (buffer)

Fluxurile de caractere cu o zona tampon (buffer) permit utilizarea unei zone tampon pentru cresterea eficientei operatiilor de citire.
Fluxurile de caractere de intrare cu tampon folosesc clasa BufferedReader. Crearea (deschiderea) unui flux de caractere cu tampon se realizeaza cu ajutorul constructorilor clasei BufferedReader. Constructorii clasei BufferedReader au una din formele: a) BufferedReader(Reader <in>) unde:

- <in> - reprezinta fluxul original de tip Reader.


Nota: Zona tampon are o lungime care este aleasa implicit (automat). b) BufferedReader(Reader <in>, int <lg_buffer>) - <in> - reprezinta fluxul original de tip Reader; - <lg_buffer> - reprezinta lungimea zonei tampon a fluxului de intare.
3/2/2014 43

unde:

Dintr-un flux de caractere cu tampon se poate citi folosind metodele read() si

read (char [] <c>, int <poz_ini>, int <lungime>) , asemanatoare celor descrise pentru clasa FileReader.
Metodele skip(), ready() si close() sunt asemanatoare celor descrise pentru clasa FileReader. Programul urmator (CitesteSiruri.java) citeste doua siruri de caractere de la tastatura si le stocheaza intr-un tablou de caractere de lungime 20. Daca dupa citirea primului sir, in zona tampon mai exista caractere necitite (ceea ce inseamna ca s-a introdus un sir de lungime mai mare de 20) atunci acestea vor fi sarite din fluxul de intrare pentru a permite eliberarea zonei tampon si citirea de la tastatura a celui de al doilea sir.
import java.io.*; class CitesteSiruri { public static void main(String[] args) { char[] caractere1 = new char[20]; char[] caractere2 = new char[20]; for (int i=0; i <=19; i++) caractere1[i] = ' '; for ( int i=0; i <=19; i++) caractere2[i] = ' ';
3/2/2014 44

try { BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); System.out.println ("Introduceti primul sir"); br.read(caractere1, 0, 20); String sir1 = new String(caractere1); System.out.println(sir1); while (br.ready() ) br.skip (1); System.out.println ("Introduceti al doilea sir"); br.read(caractere2, 0, 20); String sir2 = new String(caractere2); System.out.println(sir2); boolean rezultat = false; rezultat = sir1.equals(sir2); if (rezultat ==true) System.out.println ("siruri egale"); else System.out.println ("siruri diferite"); } catch(IOException e) { System.out.println ("Eroare la sirul citit" + e.getMessage()); } } }
3/2/2014 45

Metoda readLine() citeste din fluxul de intrare o linie de text. Metoda returneaza un obiect de tip String care contine linia de text citita din flux , fara a include si caracterul (sau caracterele) care reprezinta sfarsitul de linie. Daca se ajunge la sfarsitul fluxului, valoarea sirului returnat va fi null.
Sfarsitul de linie este indicat astfel:

- un caracter de linie noua (newline - \n);


- un caracter de retur de car (carriage return - \r); - un retur de car urmat de o linie noua. Ca exemplu, putem ilustra deschiderile de flux de intare cu tampon si citirile de linii de text de la tastatura, facute in aproape toate programele Java prezentate pana acum. Dintr-un fisier se poate citi o intreaga linie de text, si nu caracter cu carecter, daca se foloseste un flux de caractere cu tampon de tip BufferedReader suprapus peste un flux de tip FileReader.

Programul urmator (CitesteLiniiFisier.java) ilustreaza modul de citire linie cu linie dintr-un fisier care contine instructiuni Java (numit CitesteLiniiFisier.java), folosind un flux de caractere cu zona tampon.
3/2/2014 46

import java.io.*; public class CitesteLiniiFisier { public static void main (String [] args) { try { BufferedReader fisier = new BufferedReader( new FileReader("CitesteLiniiFisier.java")); boolean eof = false; while(!eof) { String linie = fisier.readLine(); if (linie == null) eof = true; else System.out.println(linie); } fisier.close(); } catch(IOException e) { System.out.println("Eroare: " + e.getMessage()); } } }
3/2/2014 47

A.3 Fluxuri filtrate de caractere de intrare cu o zona tampon care tin evidenta numerelor de linie Fluxurile de caractere de intrare cu tampon care tin evidenta numerelor de linie dintrun fisier folosesc clasa LineNumberReader. Acest filtru al fluxului de intrare urmareste numarul de linie pe masura citirii din fluxul de intrare. Crearea (deschiderea) unui flux de caractere cu tampon care tin evidenta numerelor de linie se realizeaza cu ajutorul constructorilor clasei LineNumberReader. Constructorii clasei LineNumberReader au una din formele: a) LineNumberReader(Reader <in>) - <in> - reprezinta fluxul original de tip Reader. Nota: Zona tampon are o lungime care este aleasa implicit (automat). b) unde:

LineNumberReader(Reader <in>, int <lg_buffer>)


- <in> - reprezinta fluxul original de tip Reader; - <lg_buffer> - reprezinta lungimea zonei tampon a fluxului de intare.
3/2/2014

unde:

48

Metodele pentru citirea, inchiderea, testarea unui flux de intrare cu tampon sunt mostenite de la clasa BufferedReader si ele au fost prezentate deja. In plus, aceasta clasa ofera metoda getLineNumber() care este folosita pentru a obtine numarul liniei curente din fluxul de intrare atunci cand acesta este citit cu metoda readLine(). Metoda returneaza un intreg care reprezinta numarul liniei curente din flux. Dintr-un fisier se poate citi o intreaga linie de text si se poate tine evidenta numerelor citite daca se foloseste un flux de caractere cu tampon de tip LineNumberReader suprapus peste un flux de tip FileReader. Programul urmator (CitesteLiniiFisier.java) afiseaza numerele liniilor citite dintr-un fisier care contine instructiuni Java (numit CitesteLiniiFisier1.java), folosind un flux de caractere cu zona tampon tip LineNumberReader.

3/2/2014

49

import java.io.*; public class CitesteLiniiFisier1 { public static void main (String [] args) { try { LineNumberReader fisier = new LineNumberReader(new FileReader("CitesteLiniiFisier1.java")); boolean eof = false; while(!eof) { String linie = fisier.readLine(); if (linie == null) eof = true; else System.out.println(fisier.getLineNumber() + " " + linie); } fisier.close(); } catch(IOException e) { System.out.println("Eroare: " + e.getMessage()); } } }
3/2/2014 50

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