Se afișează postările cu eticheta stream. Afișați toate postările
Se afișează postările cu eticheta stream. Afișați toate postările

joi, 15 ianuarie 2026

Fișă pentru Laborator Fluxuri la nivel de octet

1. Analizați reperele teoretice:
https://musteatadidactic.blogspot.com/2026/01/fluxuri-de-citirescriere-la-nivel-de.html

2. Executați în editorul de cod Java preferat Exemplul 1 prezentat în material, înlocuiți instrucțiunea throw cu blocuri try … catch … finally, astfel încât să gestionați excepțiile în mod corespunzător. Atașați fiecărui o instrucțiune System.out.println ce va afișa numele și prenumele dvs. Fișierele sursă salvați în dosar pe drive.

3. Executați în editorul de cod Java preferat Exemplul 2 prezentat în material. Completați fișierul cu datele pentru încă 3 persoane. Afișați la ecran toate persoanele. Afișați textul Elevi restanțieri urmat de datele elevilor restanțieri.

4. Utilizatorul introduce de la tastatură un șir de x numere întregi. Salvați aceste numere în fișier binar. Citiți numerele din fișier binar și afișați suma acestora. Folosiți clasele DataOutputStream și DataInputStream.

5. De la tastatură se introduce dimensiunea și valorile unui vector (tablou unidimensional). Transmiteți într-un fișier binar doar elementele impare. Citiți datele din fișier și afișați la ecran informația.
Notă. Dat fiind faptul că nu cunoaștem câte valori vor fi în fișier avem nevoie de o instrucțiune care ar citi până ajungem la sfârșit de fișier. O soluție ar fi:
try {
while (true) {
int numar = input.readInt();
System.out.print(numar + " ");
}
} catch (EOFException e) {
// sfârșitul fișierului
}

6. De la tastatură se introduce dimensiunea și valorile unui vector (tablou unidimensional). Transmiteți într-un fișier binar elementele divizibile la 5, iar în alt fișier binar celelalte elemente.

7. De la tastatură se introduce numărul de zile pentru care s-a monitorizat temperatura în grade Celsius. După care denumirea zilei urmată de temperatura (double) în ziua respectivă. Salvați datele într-un fișier binar. Citiți datele și afișați zilele cu temperaturile corespunzătoare. În câte zile temperatura a fost sub 0 grade? Afișați la ecran.

8. De la tastatură se introduce numărul de produse din magazin. Pentru fiecare produs se introduce: denumirea produsului (String), prețul produsului (double) și numărul de exemplare (int). Salvați datele într-un fișier binar. Citiți datele din fișier și afișați lista produselor cu prețurile lor. Afișați și numărul produselor cu prețul mai mare de 100 lei și valoarea totală a produselor aflate în magazin.

9. De la tastatură se introduce numărul de cărți din bibliotecă. Pentru fiecare carte se introduce: titlul cărții (String), autorul cărții (String) și numărul de exemplare disponibile (int). Salvați datele într-un fișier binar. Citiți datele din fișier și afișați lista cărților din bibliotecă. Afișați și numărul total de exemplare din bibliotecă.

Temă pentru acasă

Citiți reperele teoretice și notați în caiete ideile principale, organizându-le sub forma răspunsurilor la următoarele întrebări:
Ce sunt fluxurile de intrare și ieșire la nivel de octet?
Ce clase permit lucrul cu fluxuri la nivel de octet în Java?
Cum se realizează scrierea și citirea datelor la nivel de octet?
Unde sunt utilizate fluxurile binare în aplicații?
De ce sunt utilizate aceste tipuri de fluxuri?

Succes!
❤️

marți, 6 ianuarie 2026

Fluxuri de citire/scriere la nivel de octet

În lecțiile precedente am învățat ce reprezintă fluxurile de intrare și ieșire și cum se utilizează acestea la nivel de caractere.

În lecția de astăzi ne vom concentra pe modul de lucru cu fluxurile binare în limbajul de programare Java. Adică vom învăța cum se realizează citirea și scrierea datelor în fișiere binare. 


După cum cunoaștem, în limbajul Java, pentru a implementa orice funcționalitate, trebuie să cunoaștem clasele care ne permit realizarea ei, precum și constructorii și metodele specifice ale acestor clase.


La baza ierarhiei fluxurilor bazate pe octeți se află clasele abstracte OutputStream (pentru scriere) și InputStream (pentru citire). Cunoașterea metodelor acestor clase ne permite, practic, să stăpânim aproximativ 90% din funcționalitatea tuturor claselor care le moștenesc, deoarece anume cu aceste clase lucrăm de fapt.

Clasa
InputStream conține următoarele metode:

1) public abstract int read() throws IOException;
– citește octetul curent din flux şi îl returnează sub forma unui întreg cu valori între 0 şi 255. Dacă s-a ajuns la capătul fluxului se returnează valoarea –1
2) public int read(byte b[]) throws IOException;
- citesc de la poziția curentă din flux un număr de octeți egal cu lungimea tabloului b şi îl înscriu în tabloul b, returnează numărul de octeţi citiţi în bufferul b sau –1 dacă s-a ajuns la capătul fluxului.
3) public int read(byte b[], int off, int len) throws IOException;
- citesc de la poziția curentă din flux un număr de octeţi egal cu len şi îl înscriu în tabloul b, la poziția off. Returnează numărul de octeţi citiţi în bufferul b sau –1 dacă s-a ajuns la capătul fluxului.
4) public long skip(long n) throws IOException;
- mută poziția cursorului de citire peste n octeţi, întorcând numărul efectiv de octeţi peste care s-a sărit, sau -1 în caz de EOF.
5) public int available() throws IOException;
- returnează numărul de octeţi disponibili pentru citire din flux.
6) public void close() throws IOException;
- închide un flux. Odată terminat lucrul cu un flux, acesta trebuie închis, eliberând astfel resursele sistem ocupate de acel flux. În mod normal JVM închide aceste fluxuri în momentul în care programul se termină, dar este recomandabil ca programatorul să facă „curat”.
7) public synchronized void mark(int readlimit);
- prin această funcție se memorează poziția curentă în flux, specificând prin argumentul readlimit, maximul de octeţi (se crează un buffer de dimensiune readlimit) care se pot citi până la apelul funcției reset.
8) public synchronized void reset() throws IOException;
- repoziționează cursorul de citire din flux la poziția la care s-a făcut marcarea prin funcția mark.
9) public boolean markSupported(); - returnează adevărat daca metodele mark() și reset() sunt implementate, și fals în caz contrar.
10) protected void finalize() throws IOException;- asigură apelarea metodei close() pentru fluxul curent în caz că nu mai sunt referinţe la acesta.

Pentru a utiliza clasa InputStream în programare a fost nevoie de construirea unor clase derivate din aceasta, clase care să fie conectate cu surse de date reale existente în sistem.

Din categoria claselor pentru fluxuri de intrare la nivel de octet conectate la diferite tipuri de resurse fac parte:
● ByteArrayInputStream permite conectarea unui flux la un tablou de octeţi.
● SequenceInputStream permite combinarea mai multor fluxuri având ca rezultat obținerea unui singur flux.
● AudioInputStream permite conectării cu un stream audio.
● FileInputStream oferă posibilitatea conectării cu un fişier pentru a citi datele înregistrate în acesta.

Clasa OutputStream conține următoarele metode:

1) public abstract void write(int i) throws IOException; - scrie în flux octetul cel mai puţin semnificativ al argumentului, care este de tip întreg.
2) public void write (byte b[]) throws IOException;- permit scrierea în flux a unui tablou de octeţi .
3) public void write (byte b[], int off, int len) throws IOException;- permit scrierea în flux a unei secțiuni din tabloul de octeţi b începând de la poziția off şi având lungimea len.
4) public long flush() throws IOException; - forţează transmiterea datelor la destinație (capătul flux-ului) şi este utilă în cazul în care se folosește un buffer de scriere (golește buffer-ul).
5) public void close() throws IOException; - închide fluxul deschis .

În cadrul acestui curs utiliza mai multe clase pentru a opera cu fluxurile la nivel de octeți. Toate metodele sunt moștenite de la clasele InputStream şi OutputStream, nu au metode noi.

Clasa FileInputStream are constructorii :

1) FileInputStream(File file) throws FileNotFoundException – va realiza conectarea cu un fişier concret. Numele și calea către fișier fiind setate cu ajutorul unei instanțe a clasei File.
2) FileInputStream(String name) - va realiza conectarea cu un fișier calea căruia este dată de name.

Clasa FileOutputStream are un singur constructor:

FileOutputStream (cale catre fisier);

Exemplu 1. Programul va crea un fișier binar numit binar.dat, va scrie în fișier primele 10 numere naturale la nivel de octet, folosind FileOutputStream. Va deschide fișierul pentru citire folosind FileInputStream și va afișa pe ecran toate valorile citite, separate prin spațiu.
import java.io.*;
public class Main {
public static void main(String[] args) throws IOException{

FileOutputStream output = new FileOutputStream("binar.dat");
for (int i=1;i<=10;i++) output.write(i);
output.close();

FileInputStream input = new FileInputStream("binar.dat");
int value;
while((value=input.read()) != -1)
System.out.print(value + " ");
input.close();

}}
Fișierul binar.dat creat în exemplul de mai sus este un fișier binar. Va putea fi citit de un program Java însă nu de un editor de text.


Extensia .dat este pur și simplu un nume generic pentru extensia fișierului creat. Nu are o semnificație aparte în Java sau în sistemul de operare.
Astfel puteți crea o extensie personalizată. De exemplu, .xyz sau .info pentru fișierele tale, atâta timp cât programul tău știe cum să le citească și să le scrie.
De exemplu:
FileOutputStream output = new FileOutputStream("date_elevi.myext");

Fișierul va avea extensia .myext, iar Java îl va percepe la fel ca pe orice fișier binar. 👌

După ce am învățat cum se utilizează clasele
FileInputStream și FileOutputStream pentru citirea și scrierea simplă a octeților, următorul pas este să folosim clase care ne permit să lucrăm cu date structurate: DataInputStream și DataOutputStream, care extind funcționalitatea fluxurilor binare pentru a citi și scrie direct tipuri de date primitive. 

Clasa
DataInputStream permite citirea octeţilor din flux şi convertirea lor la un tip dorit.Constructor: 
DataInputStream(InputStream fluxIntrare);

Metode:
1) boolead readBoolean() throws IOException;
2) byte readByte() throws IOException;
3) short readShort() throws IOException;
4) char readChar() throws IOException;
5) int readInt() throws IOException;
6) long readLong() throws IOException;
7) float readFloat() throws IOException;
8) double readDouble() throws IOException;
9) String readUTF() throws IOException;
10)void close() throws IOException;


Clasa DataOutputStream converteşte valorile primitive sau șiruri de caractere în octeţi şi le transmite la ieşire prin flux. Constructor:
 DataOutputStream(OutputStream fluxIesire);

Metode:
1) void writeBoolean(boolean b) throws IOException;
2) void writeByte(int b) throws IOException;
3) void writeBytes(String s) throws IOException;
4) void writeShort(int s) throws IOException;
5) void writeChar(int c) throws IOException;
6) void writeInt(int i) throws IOException;
7) void writeLong(long l) throws IOException;
8) void writeFloat(float f) throws IOException;
9) void writeDouble(double d) throws IOException;
10) void writeUTF(String s) throws IOException; 

Exemplul 2. Programul va crea fișierul binar numit out.dat folosind DataOutputStream. Va scrie în fișier numele și nota a trei elevi folosind metodele writeUTF() și writeDouble(). Apoi va citi din fișier datele cu ajutorul metodelor clasei DataInputStream și va afișa pe ecran numele și nota fiecărui elev. 
import java.io.*;
public class Main {
public static void main(String [] args) throws IOException{
DataOutputStream output=new DataOutputStream(new FileOutputStream("out.dat"));
output.writeUTF("Mihai"); output.writeDouble(9.56);
output.writeUTF("Ion"); output.writeDouble(9.81);
output.writeUTF("Maria"); output.writeDouble(9.60);
output.close();

DataInputStream input=new DataInputStream(new FileInputStream("out.dat"));
System.out.println(input.readUTF()+" "+input.readDouble());
System.out.println(input.readUTF()+" "+input.readDouble());
System.out.println(input.readUTF()+" "+input.readDouble());
input.close();
}
}



Exemplul 3. Programul va crea fișierul binar numit out.dat folosind DataOutputStream. Va scrie în fișier numele și nota citite de la tastatură a n elevi. Apoi va citi din fișier datele cu ajutorul metodelor clasei DataInputStream și va afișa pe ecran numele și nota fiecărui elev. 
import java.io.*;
import java.util.Scanner;
public class Main {
public static void main(String[] args) throws IOException {
Scanner scanner = new Scanner(System.in);
System.out.print("Introduceți numărul de elevi: ");
int n = scanner.nextInt();
scanner.nextLine(); // consumă Enter-ul rămas după nextInt()

DataOutputStream output = new DataOutputStream(new FileOutputStream("out.dat"));
for (int i = 0; i < n; i++) {
System.out.print("Introduceți numele elevului " + (i+1) + ": ");
String nume = scanner.nextLine();
System.out.print("Introduceți nota elevului " + (i+1) + ": ");
double nota = scanner.nextDouble();
scanner.nextLine(); // consumă Enter-ul rămas
output.writeUTF(nume);
output.writeDouble(nota);
}
output.close();

DataInputStream input = new DataInputStream(new FileInputStream("out.dat"));
System.out.println("\nLista elevilor cu notele lor:");
try {
for (int i = 0; i < n; i++) {
String nume = input.readUTF();
double nota = input.readDouble();
System.out.println(nume + " " + nota);
}} catch (EOFException e) {
// Sfârșitul fișierului
}
input.close();
}}
Fișierul binar out.dat a fost creat și în el au fost salvate datele introduse de la tastatură. Deoarece este un fișier binar, acesta nu poate fi citit direct cu un editor de text, de aceea trebuie să oferim o modalitate de a verifica ce informații au fost stocate.
În acest scop, în metoda
main() sunt incluse și instrucțiuni care citesc datele din fișier și le afișează pe ecran, astfel încât să putem vedea conținutul salvat.

Limbajul Java oferă oportunități de a salva și starea obiectelor în fișiere binare. De ce apare această necesitate? 
Atunci când lucrăm cu obiecte, în mod normal, acestea există doar pe durata execuției programului. După terminarea programului sau atunci când nu mai există referințe către ele, obiectele sunt eliminate automat din memorie de Garbage Collector.
Există însă situații în care dorim ca datele unui obiect să fie păstrate și după închiderea programului, pentru a putea fi utilizate ulterior.
În astfel de cazuri, limbajul Java permite salvarea obiectelor într-un fișier în format de obiect, printr-un proces numit serializare. Astfel, starea obiectului este salvată într-un fișier și poate fi refăcută mai târziu în program, atunci când este nevoie.
Dar despre serializare vom discuta într-o altă postare! 💬

Succes!
❤️

luni, 5 ianuarie 2026

Fluxuri de citire și scriere la nivel de caractere

Ce sunt fluxurile în general în limbajul Java, dar și fluxurile la nivel de caractere am explorat în postarea 👉 Fluxuri în Java
Vom analiza mai jos clasele Java care permit operarea cu  fluxurile de caractere
  • FileReader
  • FileWriter
  • BufferedReader
  • BufferedWriter
Acestea permit programelor să citească și să scrie text în fișiere într-un mod simplu.

Clasa FileReader este utilizată pentru citirea caracterelor dintr-un fișier text. Pentru a putea folosi această clasă, trebuie mai întâi să creăm un obiect FileReader, iar acest lucru se face prin constructori.

Clasa FileReader are doi constructori principali: 
  • FileReader(String cale)- primește ca parametru calea către fișier, sub formă de text, String. Programul deschide fișierul respectiv pentru citire.
  • FileReader(File fisier)- primește ca parametru un obiect de tip File care reprezintă fișierul ce trebuie citit. Mai întâi se creează obiectul File, iar apoi acesta este transmis constructorului FileReader.
Exemplu comparativ: 
// varianta 1
FileReader fr1 = new FileReader("text.txt");
// varianta 2
File f = new File("text.txt");
FileReader fr2 = new FileReader(f);

Ambele variante deschid același fișier pentru citire. 

Metode importante ale clasei FileReader
  • read() - citește un caracter din fișier
  • close() - închide fișierul, fluxul de intrare deschis
Exemplu 1. Citirea datelor din fișier cu metoda read() a clasei FileReader.
import java.io.*;
public class Main{
public static void main(String[] args) throws IOException {
FileReader fr = new FileReader("D:\\documente\\TestFile1.txt");
int c;
while ((c = fr.read()) != -1) {
System.out.print((char)c);
}
fr.close();
}}
Variabila c, de tip întreg (int), stochează codul numeric al caracterului citit din fișier. 
Metoda read() returnează un număr întreg care este codul caracterului citit din fișier, iar la sfârșitul fișierului returnează valoarea -1, ceea ce înseamnă că nu mai este nimic de citit.

Exemplu 2. Citirea datelor din fișier cu metodele clasei Scanner.
import java.io.*;
import java.util.Scanner;
public class Main{
public static void main(String[] args) throws IOException {
FileReader fr = new FileReader("D:\\documente\\TestFile1.txt");
Scanner sc = new Scanner(fr);
while (sc.hasNextLine()) {
String linie = sc.nextLine();
System.out.println(linie);
}
sc.close();
fr.close();
}}

Pentru ca programul să citească și să afișeze numere din fișier, este mai potrivit să folosim clasa
Scanner, deoarece aceasta poate identifica direct valori numerice (int, double etc.). FileReader va deschide fișierul, iar Scanner va citi numerele din el.

Exemplu 3. Citirea datelor de tip primitiv din fișier cu metodele clasei Scanner.
import java.io.*;
import java.util.*;
public class Main{
public static void main(String[] args) throws IOException {
FileReader fr = new FileReader("D:\\documente\\TestFile1.txt");
Scanner sc = new Scanner(fr);
System.out.println("Fisierul contine valorile");
while (sc.hasNextInt()) {
int numar = sc.nextInt();
System.out.print(numar + " ");
}
sc.close();
fr.close();
}}

Clasa
Scanner este foarte practică atunci când dorim să citim numere, cuvinte sau linii întregi din fișiere, deoarece identifică automat tipul datelor.😍

Clasa BufferedReader este utilizată pentru citirea eficientă a textului din fișiere. Aceasta folosește un buffer (memorie temporară) pentru a accelera citirea. Cel mai mare avantaj este metoda readLine(), care citește o linie întreagă. Constructorii clasei sunt: 
  • BufferedReader(Reader in) - creează un obiect BufferedReader care citește date dintr-un flux de caractere (Reader). În practică, cel mai des se folosește împreună cu FileReader pentru citirea unui fișier text. Cel mai utilizat constructor.
Exemplu: BufferedReader br = new BufferedReader(new FileReader("text.txt"));
  • BufferedReader(Reader in, int dimBuffer)- acest constructor permite specificarea dimensiunii bufferului (memoria temporară utilizată pentru citire) la instanțiere. Reader in este fluxul de caractere din care se citește, iar dimBuffer este dimensiunea bufferului (numărul de caractere).
Exemplu: BufferedReader br = new BufferedReader(new FileReader("text.txt"), 1024);

Exemplu 4. Citirea datelor din fișier folosind clasa FileReader și BufferedReader.
import java.io.*;
public class Main{
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new FileReader("D:\\documente\\TestFile1.txt"));
String linie;
while ((linie = br.readLine()) != null) {
System.out.println(linie);
}
br.close();
}}
Metoda br.readLine() returnează un String, linia curentă din fișier. Pentru a obține un număr trebuie să folosim metode de conversie:
    • Integer.parseInt() - convertește stringul citit în int
    • Double.parseDouble() - convertește stringul citit în double
    • Float.parseFloat() - convertește stringul citit în float
Exemplu 5. Citirea datelor din fișier folosind clasa FileReader și BufferedReader în cazul în care pe fiecare linie se află o valoare.
import java.io.*;
public class Main{
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new FileReader("D:\\documente\\TestFile1.txt"));
String linie;
while ((linie = br.readLine()) != null) {
int numar = Integer.parseInt(linie);
System.out.println(numar);
} br.close();
}}

Exemplu 6. Citirea datelor din fișier folosind clasa FileReader și BufferedReader în cazul în care pe fiecare linie se află mai multe valori.
import java.io.*;
public class Main{
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new FileReader("D:\\documente\\TestFile1.txt"));
String linie;
while ((linie = br.readLine()) != null) {
String[] numere = linie.split(" ");
for (String n : numere) {
int numar = Integer.parseInt(n);
System.out.println(numar);
}}
br.close();
}}

BufferedReader nu citește direct numere, ci text. De aceea citirea numerelor din fișiere, în practică este mai simplu să folosim Scanner, deoarece el poate citi direct numere (nextInt(), nextDouble()), fără conversii.

Exemplu 7. Citirea datelor din fișier folosind clasa FileReader și Scanner în cazul în care pe fiecare linie se află mai multe valori de diferite tipuri. Cum ar fi int, String și String:
import java.io.*;
import java.util.*;
public class Main{
public static void main(String[] args) throws IOException {
Scanner sc = new Scanner(new FileReader("D:\\documente\\TestFile1.txt"));
while (sc.hasNext()) {
int id = sc.nextInt();
String nume = sc.next();
String prenume = sc.next();
System.out.println("ID: " + id +
" Nume: " + nume +
" Prenume: " + prenume);
} sc.close();
}}

Exemplu 8. Citirea datelor din fișier folosind clasa FileReader și BufferedReader în cazul în care pe fiecare linie se află mai multe valori de diferite tipuri. Cum ar fi intString și String:
import java.io.*;
public class Main{
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new FileReader("D:\\documente\\TestFile1.txt"));
String linie;
while ((linie = br.readLine()) != null) {
String[] date = linie.split("\\s+");
int id = Integer.parseInt(date[0]);
String nume = date[1];
String prenume = date[2];
System.out.println("ID: " + id +" Nume: " + nume + " Prenume: " + prenume);
}
br.close();
}}

În ambele programe se citește date dintr-un fișier și se afișează câte un int urmat de două String (ID, Nume, Prenume).
Varianta cu Scanner citește fișierul element cu element (nextInt(), next()), fiind simplă și directă pentru date bine structurate.
Varianta cu BufferedReader citește fișierul linie cu linie, apoi separă elementele cu split(), oferind mai mult control asupra procesării liniei și este mai eficientă pentru fișiere mari.
Practic, ambele obțin același rezultat, dar dacă ai un fișier mic și vrei cod rapid și clar, Scanner e ok, pentru fișiere mari sau procesări mai complexe, BufferedReader e mai performant.

Pentru a scrie sau transmite date (caractere) în fișiere text este clasa FileWriter care are mai mulți constructori principali, care permit să creezi un obiect FileWriter în funcție de ce informații ai despre modul în care trebuie să ajungă datele în fișier: 
  • FileWriter(String fileName) - creează un fișier sau îl deschide dacă există. Dacă fișierul există, suprascrie conținutul.
  • FileWriter(String fileName, boolean append) - la fel ca primul constructor, doar că al doilea parametru true înseamnă că se adaugă la sfârșitul fișierului (append). Astfel  că, la conținutul deja existent în fișier se adaugă noua informație. Valoarea false sau lipsa celui de al doilea parametrul va suprascrie fișierul.
  • FileWriter(File file) - Primește un obiect File în loc de șir. Comportament similar primului constructor, suprascrie fișierul dacă există.
  • FileWriter(File file, boolean append) Primește un obiect File în loc de șir. Pentru valoara true în cel de al doilea parametru va efectua anexarea datelor în fișier păstrând conținutul anterior.
Exemplu 9. Scrierea unei propoziții în fișier folosind clasa FileWriter:
import java.io.*;
public class Main{
public static void main(String[] args) throws IOException {
String propozitie = "Aceasta este o propoziție scrisă în fișier.";
FileWriter fw = new FileWriter("D:\\documente\\Propozitie.txt");
fw.write(propozitie);
fw.close();
System.out.println("Propoziția a fost scrisă cu succes!");
}}
 


Exemplu 10. Scrierea în fișier folosind clasa FileWriter a datelor introduse de utilizator de la tastatură:
import java.io.*;
import java.util.*;
public class Main{
public static void main(String[] args) throws IOException {
Scanner in = new Scanner(System.in);
System.out.println ("Ce ID? ");
int id = in.nextInt();
System.out.println ("Ce nume? ");
String nume = in.next();
System.out.println ("Ce prenume? ");
String prenume = in.next();
FileWriter fw = new FileWriter("D:\\documente\\Date.txt");
fw.write(id + " " + nume + " " + prenume + "\n");
System.out.println("Datele au fost scrise cu succes în fișier!");
fw.close(); in.close();
}}
  

Vă mai amintiți de instrucțiunea try cu resurse? Să modificăm exemplul anterior: 

Exemplu 11. Scrierea în fișier folosind clasa FileWriter a datelor introduse de utilizator de la tastatură folosind instrucțiuea try cu resurse pentru tratarea excepțiilor:
import java.io.*;
import java.util.*;
public class Main{
public static void main(String[] args){
try (Scanner in = new Scanner(System.in);
FileWriter fw = new FileWriter("D:\\documente\\Date.txt"))
{
System.out.print("Ce ID? ");
int id = in.nextInt();
System.out.print("Ce nume? ");
String nume = in.next();
System.out.print("Ce prenume? ");
String prenume = in.next();
fw.write(id + " " + nume + " " + prenume + "\n");
System.out.println("Datele au fost scrise cu succes în fișier!");
} catch (IOException e) {
System.out.println("Eroare la scrierea fișierului: " + e.getMessage());
}}}
Avantajele instrucțiunii try cu resurse este că resursele sunt tot închise automat, nu mai trebuie să apelăm metoda close().

Clasa BufferedWriter este o clasă folosită pentru a scrie caractere în fișiere.
Diferența față de FileWriter este că folosește un buffer intern, adică stochează temporar datele în memorie și le scrie dintr-un bloc în fișier.
Oferă o performanță mai bună decât scrierea caracter cu caracter și poate scrie linii întregi cu metoda newLine().
Constructori: 
  • BufferedWriter(Writer out) - creează un BufferedWriter care scrie în fișierul specificat prin Writer. Folosește dimensiunea implicită a bufferului (~8192 caractere).
Exemplu: FileWriter fw = new FileWriter("D:\\documente\\Date.txt");
BufferedWriter bw = new BufferedWriter(fw);
  • BufferedWriter(Writer out, int sz) - creează un BufferedWriter cu un buffer personalizat de sz caractere. Poate fi util pentru fișiere foarte mari sau scrieri frecvente.  
ExempluFileWriter fw = new FileWriter("D:\\documente\\Date.txt");
BufferedWriter bw = new BufferedWriter(fw, 4096);

Exemplu 12. Scrierea în fișier folosind clasa BufferWriter a datelor introduse de utilizator de la tastatură:
import java.io.*;
import java.util.*;
public class Main{
public static void main(String[] args) throws IOException{
Scanner in = new Scanner(System.in);
System.out.print("Ce ID? ");
int id = in.nextInt();
System.out.print("Ce nume? ");
String nume = in.next();
System.out.print("Ce prenume? ");
String prenume = in.next();
BufferedWriter bw = new BufferedWriter(new FileWriter("D:\\documente\\Date.txt"));
bw.write(id + " " + nume + " " + prenume);
bw.newLine(); // adaugă linie nouă
System.out.println("Datele au fost scrise cu succes în fișier!");
bw.close();
in.close();
}}
  

Cam asta e pe scurt despre citirea/ scrierea la nivel de caractere din/în documente text. Data viitoare vorbim despre fluxuri de octeți 👌

Succes!
❤️

duminică, 4 ianuarie 2026

Fluxuri de intrare și fluxuri de ieșire

În Java operațiile de intrare / ieșire au la bază termenul de stream (flux) introdus pentru prima dată de Dennis Ritchie care în 1984 implementează primul sistem I/O pe baza de stream în cadrul S.O. Unix. 
Ideea de stream are la bază crearea unui canal de comunicaţie între două entităţi. Una dintre entităţi este sursa, iar cealaltă destinaţia. 
Sursa scrie informaţii în canal, iar destinaţia citeşte aceste date. 
Canalul permite trecerea unui flux de date într-o singură direcţie. 
Deoarece există două direcţii de comunicare, există două tipuri mari de stream-uri: de intrare (input stream) și de ieșire(output stream)
Un flux care citește date se numește de intrare, iar cel care scrie date se numește de ieșire.

Java oferă mai multe clase și interfețe pentru lucrul cu fluxurile de intrare /ieșire grupate în pachetul în pachetul java.io.

Majoritatea metodelor claselor I/O pot genera excepții care trebuie tratate. Cum ? Studiați aici 👉 Tratarea excepțiilor în Java

Fluxurile de date, atât cele de intrare (citire), cât și cele de ieșire (scriere), pot fi de două tipuri: fluxuri de octeți și fluxuri de caractere.

Pentru a înțelege diferența dintre aceste două tipuri de fluxuri, este bine să facem distincția dintre fișiere text și fișiere binare.

Un fișier text este un fișier al cărui conținut poate fi deschis și modificat cu un editor de text, de exemplu Notepad. În astfel de fișiere informația este salvată sub formă de caractere, iar utilizatorul poate citi direct conținutul.

În schimb, fișierele binare conțin date salvate într-un format special, care nu poate fi interpretat corect de un editor de text. Aceste fișiere sunt create pentru a fi citite și procesate de anumite programe. Exemple de fișiere binare sunt imaginile, fișierele audio, video sau programele executabile.

Un exemplu simplu care ilustrează diferența dintre fișiere text și fișiere binare este cel al fișierelor utilizate în Java.

De exemplu, fișierul sursă *.java este stocat într-un fișier text, care poate fi deschis și citit cu orice editor de text, precum Notepad sau alte editoare de programare. În schimb, fișierul *.class, care rezultă după compilarea programului, este un fișier binar, destinat să fie citit și executat de JVM (Java Virtual Machine).

În realitate, calculatorul nu face o diferență clară între fișiere text și fișiere binare, deoarece toate fișierele sunt stocate în format binar. Diferența constă în modul în care aceste date sunt interpretate și utilizate. În cazul fișierelor text, datele sunt codificate astfel încât să reprezinte caractere lizibile pentru utilizator.

Fluxurile de intrare/ieșire bazate pe caractere sunt construite pe baza fluxurilor binare, iar conversia dintre caractere și octeți se face automat. JVM se ocupă de codificarea și decodificarea caracterelor Unicode atunci când acestea sunt citite sau scrise în fișiere. Din acest motiv, fluxurile binare sunt, în general, mai eficiente, deoarece nu necesită conversii suplimentare.

În practică, este recomandat să folosim fluxuri bazate pe caractere atunci când lucrăm cu fișiere text, create de editoare de text, și fluxuri binare atunci când lucrăm cu fișiere binare, generate de programe sau de JVM.

Exemple de clase utilizate pentru fișiere binare: imagini, video, audio, fișiere executabile sau orice tip de date brute:
  • FileInputStream: citirea datelor binare din fișier
  • FileOutputStream: scrierea datelor binare în fișier
  • BufferedInputStream: citire binară mai rapidă
  • BufferedOutputStream: scriere binară mai rapidă
  • DataInputStream: citirea tipurilor primitive (int, double etc.)
  • DataOutputStream: scrierea tipurilor primitive
  • ObjectInputStream: citirea obiectelor salvate
  • ObjectOutputStream: salvarea obiectelor în fișier
Exemple de clase utilizate pentru fișiere text: .txt, .java, .html, .csv: 
  • FileReader: citirea caracterelor din fișier
  • FileWriter: scrierea caracterelor în fișier
  • BufferedReader: citirea liniilor de text
  • BufferedWriter: scrierea eficientă a textului
  • PrintWriter: scriere formatată de text
  • CharArrayReader: citirea caracterelor dintr-un tablou
  • CharArrayWriter: scrierea caracterelor într-un tablou
Un avantaj important al fișierelor binare este că ele sunt independente de schema de codificare a sistemului de operare, ceea ce le face portabile. Astfel, programele Java pot citi fișiere binare create de Java pe orice calculator. Din acest motiv, fișierele *.class sunt fișiere binare și pot fi executate de JVM pe orice sistem care suportă platforma Java. 
Succes!
💓