This shows you the differences between two versions of the page.
|
poo-ca-cd:laboratoare:io-si-gestionarea-exceptiilor [2025/11/19 13:59] florian_luis.micu [[Nice to know] File I/O - Advanced] |
poo-ca-cd:laboratoare:io-si-gestionarea-exceptiilor [2025/11/19 14:12] (current) florian_luis.micu |
||
|---|---|---|---|
| Line 3: | Line 3: | ||
| * Autori: [[stefancocioran@gmail.com | Ștefan Cocioran ]], [[miculuis1@gmail.com | Florian-Luis Micu ]], [[sorinabuf@gmail.com | Sorina-Anamaria Buf ]] | * Autori: [[stefancocioran@gmail.com | Ștefan Cocioran ]], [[miculuis1@gmail.com | Florian-Luis Micu ]], [[sorinabuf@gmail.com | Sorina-Anamaria Buf ]] | ||
| * Data publicării: 17.11.2025 | * Data publicării: 17.11.2025 | ||
| - | * Data ultimei modificări: 17.11.2025 | + | * Data ultimei modificări: 19.11.2025 |
| + | * adăugarea unei secțiuni sumare despre I/O în materia fundamentală | ||
| + | * mutarea conceptelor avansate despre I/O în secțiuni [Nice to know] | ||
| Line 500: | Line 502: | ||
| } | } | ||
| </code> | </code> | ||
| - | =====📥📤 File I/O - The Basics==== | + | =====📥📤 File I/O==== |
| Line 517: | Line 519: | ||
| Ele constituie fundamentul pentru toate comunicațiile cu **fișiere, resurse media și rețea**. | Ele constituie fundamentul pentru toate comunicațiile cu **fișiere, resurse media și rețea**. | ||
| - | ====Modalități de scriere și de citire a datelor==== | + | ====The Basics==== |
| În Java, lucrăm cu două mari tipuri de fluxuri: | În Java, lucrăm cu două mari tipuri de fluxuri: | ||
| Line 761: | Line 763: | ||
| </note> | </note> | ||
| - | ===TL;DR I/O=== | + | ===TL;DR - I/O Basics=== |
| ^ Scenariu / Tip flux ^ Cum citim ^ Cum scriem ^ | ^ Scenariu / Tip flux ^ Cum citim ^ Cum scriem ^ | ||
| Line 772: | Line 774: | ||
| + | ====[Nice to know] File I/O - Advanced==== | ||
| - | + | ===I/O Streams=== | |
| - | ====I/O Streams==== | + | |
| Majoritatea operațiilor I/O în Java se bazează pe **fluxuri (streams)**. | Majoritatea operațiilor I/O în Java se bazează pe **fluxuri (streams)**. | ||
| Line 797: | Line 799: | ||
| </spoiler> | </spoiler> | ||
| - | ===InputStream și OutputStream=== | + | ==InputStream și OutputStream== |
| Clasele [[https://docs.oracle.com/javase/8/docs/api/java/io/InputStream.html | InputStream]] și [[https://docs.oracle.com/javase/8/docs/api/java/io/OutputStream.html | OutputStream]] sunt **abstracte** și definesc interfața de bază pentru toate fluxurile de bytes în Java. Ele oferă metode pentru **citirea și scrierea datelor nestructurate**, la nivel de byte. | Clasele [[https://docs.oracle.com/javase/8/docs/api/java/io/InputStream.html | InputStream]] și [[https://docs.oracle.com/javase/8/docs/api/java/io/OutputStream.html | OutputStream]] sunt **abstracte** și definesc interfața de bază pentru toate fluxurile de bytes în Java. Ele oferă metode pentru **citirea și scrierea datelor nestructurate**, la nivel de byte. | ||
| Line 805: | Line 807: | ||
| {{ :poo-ca-cd:laboratoare:io_stream.png?450 |}} | {{ :poo-ca-cd:laboratoare:io_stream.png?450 |}} | ||
| - | <spoiler [Opțional] Moștenirea claselor InputStream și OutputStream> | + | <spoiler [Optional] Moștenirea claselor InputStream și OutputStream> |
| Deoarece toate fluxurile de bytes moștenesc structura claselor InputStream sau OutputStream, diferitele tipuri de fluxuri pot fi folosite în mod **interschimbabil**. | Deoarece toate fluxurile de bytes moștenesc structura claselor InputStream sau OutputStream, diferitele tipuri de fluxuri pot fi folosite în mod **interschimbabil**. | ||
| Line 817: | Line 819: | ||
| </spoiler> | </spoiler> | ||
| - | ==== Basic I/O ==== | + | ===Basic I/O === |
| Input-ul standard pentru o aplicație în Java se bazează pe un obiect de tip ''InputStream'', similar cu ''stdin'' din C sau ''cin'' din C++. Acesta reprezintă o sursă de date ce provine din environment-ul în care lucrăm: | Input-ul standard pentru o aplicație în Java se bazează pe un obiect de tip ''InputStream'', similar cu ''stdin'' din C sau ''cin'' din C++. Acesta reprezintă o sursă de date ce provine din environment-ul în care lucrăm: | ||
| Line 859: | Line 861: | ||
| </note> | </note> | ||
| - | ==== Character Streams ==== | + | ===Character Streams === |
| Pentru că ne dorim să lucrăm cu valori reprezentate ca text, în Java au fost introduse clasele [[https://docs.oracle.com/javase/8/docs/api/java/io/Reader.html | Reader]] și [[https://docs.oracle.com/javase/8/docs/api/java/io/Writer.html | Writer]] din pachetul ''java.io''. | Pentru că ne dorim să lucrăm cu valori reprezentate ca text, în Java au fost introduse clasele [[https://docs.oracle.com/javase/8/docs/api/java/io/Reader.html | Reader]] și [[https://docs.oracle.com/javase/8/docs/api/java/io/Writer.html | Writer]] din pachetul ''java.io''. | ||
| Line 901: | Line 903: | ||
| </note> | </note> | ||
| - | ==== Stream Wrappers ==== | + | ===Stream Wrappers === |
| Când dorim să facem mai mult decât citirea sau scrierea simplă a octeților sau caracterelor, putem folosi **fluxuri de tip filtru**. | Când dorim să facem mai mult decât citirea sau scrierea simplă a octeților sau caracterelor, putem folosi **fluxuri de tip filtru**. | ||
| Line 923: | Line 925: | ||
| ''BufferedInputStream'' citește anticipat și stochează date într-un buffer, ceea ce **reduce accesările directe la sursa reală** și **îmbunătățește performanța**. | ''BufferedInputStream'' citește anticipat și stochează date într-un buffer, ceea ce **reduce accesările directe la sursa reală** și **îmbunătățește performanța**. | ||
| - | <spoiler [Nice to know] Cum funcționează buffer-ul intern> | + | <spoiler Cum funcționează buffer-ul intern> |
| **La citire**, buffer-ul este o zonă temporară de memorie unde sunt încărcate datele dintr-un flux, de exemplu un fișier. În loc să citim un caracter sau un byte la un moment dat, fluxul preia un bloc mare de date și **îl stochează în buffer**. Apelurile ulterioare la ''read()'' iau datele **direct din buffer**, fără a accesa imediat fișierul, ceea ce crește semnificativ performanța operațiilor de citire. Practic, bufferul **reduce numărul de accesări ale sursei de date**. | **La citire**, buffer-ul este o zonă temporară de memorie unde sunt încărcate datele dintr-un flux, de exemplu un fișier. În loc să citim un caracter sau un byte la un moment dat, fluxul preia un bloc mare de date și **îl stochează în buffer**. Apelurile ulterioare la ''read()'' iau datele **direct din buffer**, fără a accesa imediat fișierul, ceea ce crește semnificativ performanța operațiilor de citire. Practic, bufferul **reduce numărul de accesări ale sursei de date**. | ||
| Line 968: | Line 970: | ||
| Codul nostru este acum optim, dar **doar dacă lucrăm cu STDIN, STDERR și STDOUT**. Dacă vrem să lucrăm cu fișiere avem nevoie de alte clase specializate. | Codul nostru este acum optim, dar **doar dacă lucrăm cu STDIN, STDERR și STDOUT**. Dacă vrem să lucrăm cu fișiere avem nevoie de alte clase specializate. | ||
| </note> | </note> | ||
| - | ====Clasa File ==== | + | === Clasa File === |
| [[https://docs.oracle.com/javase/8/docs/api/java/io/File.html | java.io.File]] oferă un mod de a **accesa informații** despre un fișier sau un director din sistemul de fișiere. | [[https://docs.oracle.com/javase/8/docs/api/java/io/File.html | java.io.File]] oferă un mod de a **accesa informații** despre un fișier sau un director din sistemul de fișiere. | ||
| Line 1022: | Line 1024: | ||
| </note> | </note> | ||
| - | ==== File Stream ==== | + | === File Stream === |
| Acum că ați înțeles ce este un fișier și cum îl puteți reprezenta cu clasa ''File'', este momentul să învățați cum să citiți și să scrieți efectiv date. În Java, pentru lucrul cu fișiere există două fluxuri fundamentale: | Acum că ați înțeles ce este un fișier și cum îl puteți reprezenta cu clasa ''File'', este momentul să învățați cum să citiți și să scrieți efectiv date. În Java, pentru lucrul cu fișiere există două fluxuri fundamentale: | ||
| Line 1064: | Line 1066: | ||
| </code> | </code> | ||
| - | === Cum scrieți date într-un fișier? === | + | == Cum scrieți date într-un fișier? == |
| Pentru scriere, folosiți ''FileOutputStream''. Dacă **fișierul nu există**, acesta este **creat automat**. Dacă **există**, conținutul este **suprascris**, cu excepția cazului în care folosiți constructorul cu flag-ul ''append'' (care va face textul să fie scris în continuare): | Pentru scriere, folosiți ''FileOutputStream''. Dacă **fișierul nu există**, acesta este **creat automat**. Dacă **există**, conținutul este **suprascris**, cu excepția cazului în care folosiți constructorul cu flag-ul ''append'' (care va face textul să fie scris în continuare): | ||
| Line 1087: | Line 1089: | ||
| </code> | </code> | ||
| - | ==== ==== | + | === === |
| <note tip> | <note tip> | ||
| Line 1097: | Line 1099: | ||
| * Pentru scriere formatată, folosiți ''PrintWriter'' | * Pentru scriere formatată, folosiți ''PrintWriter'' | ||
| </note> | </note> | ||
| - | |||
| - | ====TL;DR I/O - Modalități de scriere și de citire a datelor==== | ||
| - | |||
| - | Modalități de citire: | ||
| - | |||
| - | * **Scanner** - Ideal pentru fișiere text simple, mai ales când trebuie să parsați cuvinte sau numere ușor. | ||
| - | |||
| - | <code java> | ||
| - | try (Scanner sc = new Scanner(new File("exemplu.txt"))) { | ||
| - | while (sc.hasNext()) { | ||
| - | System.out.println(sc.next()); | ||
| - | } | ||
| - | } catch (FileNotFoundException e) { | ||
| - | e.printStackTrace(); | ||
| - | } | ||
| - | |||
| - | // citire de la tastatură | ||
| - | |||
| - | try (Scanner sc = new Scanner(System.in)) { | ||
| - | System.out.print("Introdu un număr: "); | ||
| - | int numar = sc.nextInt(); | ||
| - | System.out.println("Ai introdus: " + numar); | ||
| - | } | ||
| - | </code> | ||
| - | |||
| - | * **BufferedReader** - Recomandat pentru fișiere text mari, citește linie cu linie și este mai eficient. | ||
| - | <code java> | ||
| - | |||
| - | try (BufferedReader br = new BufferedReader(new FileReader("exemplu.txt"))) { | ||
| - | String linie; | ||
| - | while ((linie = br.readLine()) != null) { | ||
| - | System.out.println(linie); | ||
| - | } | ||
| - | } catch (IOException e) { | ||
| - | e.printStackTrace(); | ||
| - | } | ||
| - | |||
| - | // citire de la tastatură | ||
| - | |||
| - | try (BufferedReader br = new BufferedReader(new InputStreamReader(System.in))) { | ||
| - | System.out.print("Introdu un text: "); | ||
| - | String linie = br.readLine(); | ||
| - | System.out.println("Ai scris: " + linie); | ||
| - | } catch (IOException e) { | ||
| - | e.printStackTrace(); | ||
| - | } | ||
| - | </code> | ||
| - | |||
| - | * **FileInputStream** - Potrivit pentru date binare (imagini, audio, PDF) sau când aveți nevoie de control asupra octeților. | ||
| - | |||
| - | <code java> | ||
| - | try (FileInputStream fis = new FileInputStream("imagine.jpg")) { | ||
| - | byte[] buffer = new byte[1024]; | ||
| - | int bytesRead; | ||
| - | while ((bytesRead = fis.read(buffer)) != -1) { | ||
| - | // procesare date binare | ||
| - | } | ||
| - | } catch (IOException e) { | ||
| - | e.printStackTrace(); | ||
| - | } | ||
| - | </code> | ||
| - | |||
| - | Modalități de scriere: | ||
| - | * **PrintWriter** - Ideal pentru fișiere text simple. | ||
| - | |||
| - | <code java> | ||
| - | try (PrintWriter pw = new PrintWriter(new FileWriter("exemplu.txt"))) { | ||
| - | pw.println("Salut!"); | ||
| - | pw.println("Aceasta este o linie nouă."); | ||
| - | } catch (IOException e) { | ||
| - | e.printStackTrace(); | ||
| - | } | ||
| - | </code> | ||
| - | |||
| - | * **BufferedWriter** - Recomandat pentru fișiere text mari, citește linie cu linie și este mai eficient. | ||
| - | |||
| - | <code java> | ||
| - | try (BufferedWriter bw = new BufferedWriter(new FileWriter("exemplu.txt"))) { | ||
| - | bw.write("Prima linie"); | ||
| - | bw.newLine(); | ||
| - | bw.write("A doua linie"); | ||
| - | } catch (IOException e) { | ||
| - | e.printStackTrace(); | ||
| - | } | ||
| - | </code> | ||
| - | |||
| - | * **FileOutputStream** - Potrivit pentru date binare (imagini, audio, PDF) sau când aveți nevoie de control asupra octeților. | ||
| - | |||
| - | <code java> | ||
| - | try (FileOutputStream fos = new FileOutputStream("imagine.jpg")) { | ||
| - | byte[] data = { /* octeți */ }; | ||
| - | fos.write(data); | ||
| - | } catch (IOException e) { | ||
| - | e.printStackTrace(); | ||
| - | } | ||
| - | </code> | ||
| - | ====🎲 [Optional] RandomAccessFile ==== | + | ===[Optional] RandomAccessFile === |
| Până acum am discutat despre fluxuri care citesc sau scriu date secvențial, de la începutul fișierului până la sfârșit. Dar ce faceți dacă aveți nevoie să accesați direct o anumită poziție/index din fișier? Pentru asta există clasa [[https://docs.oracle.com/javase/8/docs/api/java/io/RandomAccessFile.html|java.io.RandomAccessFile]], ce vă permite să citiți și să scrieți date oriunde în fișier. RandomAccessFile implementează interfețele ''DataInput'' și ''DataOutput'', ceea ce înseamnă că puteți folosi metodele pentru citirea și scrierea tipurilor primitive Java și a șirurilor, la fel ca în ''DataInputStream'' și ''DataOutputStream''. Totuși, nu este o subclasă a ''InputStream'' sau ''OutputStream'', deoarece oferă acces aleatoriu, nu secvențial. | Până acum am discutat despre fluxuri care citesc sau scriu date secvențial, de la începutul fișierului până la sfârșit. Dar ce faceți dacă aveți nevoie să accesați direct o anumită poziție/index din fișier? Pentru asta există clasa [[https://docs.oracle.com/javase/8/docs/api/java/io/RandomAccessFile.html|java.io.RandomAccessFile]], ce vă permite să citiți și să scrieți date oriunde în fișier. RandomAccessFile implementează interfețele ''DataInput'' și ''DataOutput'', ceea ce înseamnă că puteți folosi metodele pentru citirea și scrierea tipurilor primitive Java și a șirurilor, la fel ca în ''DataInputStream'' și ''DataOutputStream''. Totuși, nu este o subclasă a ''InputStream'' sau ''OutputStream'', deoarece oferă acces aleatoriu, nu secvențial. | ||