Puoi chiudere lo stream più esterno, infatti non è necessario conservare tutti gli stream racchiusi e puoi usare Java 7 try-with-resources.
try (BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(
new GZIPOutputStream(new FileOutputStream(createdFile)))) {
// write to the buffered writer
}
Se ti iscrivi a YAGNI, o non ne avrai bisogno, dovresti solo aggiungere il codice di cui hai effettivamente bisogno. Non dovresti aggiungere codice di cui potresti aver bisogno ma in realtà non fa nulla di utile.
Prendi questo esempio e immagina cosa potrebbe andare storto se non lo facessi e quale sarebbe l'impatto?
try (
OutputStream outputStream = new FileOutputStream(createdFile);
GZIPOutputStream gzipOutputStream = new GZIPOutputStream(outputStream);
OutputStreamWriter osw = new OutputStreamWriter(gzipOutputStream);
BufferedWriter bw = new BufferedWriter(osw)
) {
// ...
}
Cominciamo con FileOutputStream che chiama open
per fare tutto il lavoro reale.
/**
* Opens a file, with the specified name, for overwriting or appending.
* @param name name of file to be opened
* @param append whether the file is to be opened in append mode
*/
private native void open(String name, boolean append)
throws FileNotFoundException;
Se il file non viene trovato, non ci sono risorse sottostanti da chiudere, quindi chiuderlo non farà alcuna differenza. Se il file esiste, dovrebbe lanciare FileNotFoundException. Quindi non c'è nulla da guadagnare provando a chiudere la risorsa da questa sola riga.
Il motivo per cui è necessario chiudere il file è quando il file viene aperto correttamente, ma in seguito viene visualizzato un errore.
Diamo un'occhiata al prossimo stream GZIPOutputStream
C'è un codice che può generare un'eccezione
private void writeHeader() throws IOException {
out.write(new byte[] {
(byte) GZIP_MAGIC, // Magic number (short)
(byte)(GZIP_MAGIC >> 8), // Magic number (short)
Deflater.DEFLATED, // Compression method (CM)
0, // Flags (FLG)
0, // Modification time MTIME (int)
0, // Modification time MTIME (int)
0, // Modification time MTIME (int)
0, // Modification time MTIME (int)
0, // Extra flags (XFLG)
0 // Operating system (OS)
});
}
Questo scrive l'intestazione del file. Ora sarebbe molto insolito per te essere in grado di aprire un file per la scrittura ma non essere in grado di scrivere anche 8 byte su di esso, ma immaginiamo che ciò possa accadere e non chiudiamo il file in seguito. Cosa succede a un file se non è chiuso?
Non si ottengono scritture non cancellate, vengono scartate e in questo caso, non vi sono byte scritti correttamente nello stream che non sono comunque bufferizzati a questo punto. Ma un file che non è chiuso non vive per sempre, invece ha FileOutputStream
protected void finalize() throws IOException {
if (fd != null) {
if (fd == FileDescriptor.out || fd == FileDescriptor.err) {
flush();
} else {
/* if fd is shared, the references in FileDescriptor
* will ensure that finalizer is only called when
* safe to do so. All references using the fd have
* become unreachable. We can call close()
*/
close();
}
}
}
Se non chiudi affatto un file, viene comunque chiuso, ma non immediatamente (e come ho detto, i dati lasciati in un buffer andranno persi in questo modo, ma a questo punto non ce ne sono)
Qual è la conseguenza di non chiudere immediatamente il file? In condizioni normali, potresti perdere alcuni dati e potenzialmente esaurire i descrittori di file. Ma se hai un sistema in cui puoi creare file ma non puoi scrivere nulla, hai un problema più grande. vale a dire, è difficile immaginare il motivo per cui si sta ripetutamente tentando di creare questo file nonostante si stia fallendo.
Sia OutputStreamWriter che BufferedWriter non generano IOException nei loro costruttori, quindi non chiariscono quale problema potrebbero causare. Nel caso di BufferedWriter, potresti ottenere un OutOfMemoryError. In questo caso attiverà immediatamente un GC, che come abbiamo visto chiuderà comunque il file.