Gli stream di input/output (I/O streams) sono una delle concetti fondamentali di Java, presenti fin dalle prime versioni del linguaggio. Questo concetto è stato originariamente sviluppato per astrarre i processi di lettura e scrittura dei dati: uno stream può essere collegato a un file, alla rete o persino alla console - per il codice appare identico.
Problema si verifica quando lo sviluppatore gestisce in modo errato gli stream, dimentica di chiuderli o confonde diversi tipi di stream (carattere e byte), il che porta spesso a perdite di risorse, distorsioni dei dati o errori durante l'esecuzione.
Soluzione: comprensione e applicazione adeguate della gerarchia degli stream di input/output (InputStream/OutputStream per i byte, Reader/Writer per i caratteri), così come la chiusura obbligatoria degli stream una volta terminato il lavoro, preferibilmente tramite try-with-resources a partire da Java 7.
Esempio di codice per la lettura e scrittura di un file:
try (BufferedReader reader = new BufferedReader(new FileReader("input.txt")); BufferedWriter writer = new BufferedWriter(new FileWriter("output.txt"))) { String line; while ((line = reader.readLine()) != null) { writer.write(line); writer.newLine(); } }
Caratteristiche principali:
Cosa succede se non chiudi uno stream di input/output in Java?
Gli stream si occupano di risorse di basso livello del sistema operativo, e non chiudere uno stream può portare a perdite di memoria, blocchi di file, malfunzionamenti dell'applicazione o addirittura esaurimento dei descrittori di file a livello di sistema operativo.
È possibile utilizzare lo stesso OutputStream per scrivere in diversi file?
No, l'OutputStream classico è rigidamente associato a una sola sorgente/destinatario di dati. Per file diversi, vanno utilizzati oggetti OutputStream diversi.
Qual è la differenza tra PrintWriter e BufferedWriter? Quando utilizzare ciascuno?
PrintWriter si specializza nell'aggiunta di metodi di stampa formattati all'output, come println(), e sa gestire l'auto-flushing. BufferedWriter, d'altra parte, migliora principalmente le prestazioni grazie alla memorizzazione nella cache. Nella maggior parte delle applicazioni, PrintWriter è preferibile per l'output di testo, ma se è necessario scrivere rapidamente caratteri o stringhe senza formattazione, BufferedWriter è più adatto.
Uno sviluppatore legge dati da un grande file utilizzando FileInputStream, non utilizza la memorizzazione nella cache e dimentica di chiudere lo stream.
Vantaggi:
Svantaggi:
Viene utilizzata la combinazione BufferedReader con try-with-resources, lettura e elaborazione avvengono in pacchetti di righe, lo stream si chiude automaticamente.
Vantaggi:
Svantaggi: