Puede cerrar la secuencia más externa, de hecho, no necesita retener todas las secuencias envueltas y puede usar Java 7 try-with-resources.
try (BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(
new GZIPOutputStream(new FileOutputStream(createdFile)))) {
// write to the buffered writer
}
Si se suscribe a YAGNI, o no lo va a necesitar, solo debe agregar el código que realmente necesita. No debería agregar código que imagina que podría necesitar, pero en realidad no hace nada útil.
Tome este ejemplo e imagine qué podría salir mal si no hiciera esto y cuál sería el impacto.
try (
OutputStream outputStream = new FileOutputStream(createdFile);
GZIPOutputStream gzipOutputStream = new GZIPOutputStream(outputStream);
OutputStreamWriter osw = new OutputStreamWriter(gzipOutputStream);
BufferedWriter bw = new BufferedWriter(osw)
) {
// ...
}
Comencemos con FileOutputStream que llama open
a hacer todo el trabajo real.
/**
* 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;
Si no se encuentra el archivo, no hay ningún recurso subyacente para cerrar, por lo que cerrarlo no hará ninguna diferencia. Si el archivo existe, debería lanzar una FileNotFoundException. Por lo tanto, no hay nada que ganar intentando cerrar el recurso solo desde esta línea.
La razón por la que necesita cerrar el archivo es cuando el archivo se abre con éxito, pero luego aparece un error.
Veamos la próxima transmisión GZIPOutputStream
Hay un código que puede lanzar una excepción
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)
});
}
Esto escribe el encabezado del archivo. Ahora sería muy inusual para usted poder abrir un archivo para escribir pero no poder escribir incluso 8 bytes, pero imaginemos que esto podría suceder y no cerramos el archivo después. ¿Qué le sucede a un archivo si no está cerrado?
No se obtienen escrituras sin vaciar, se descartan y, en este caso, no hay bytes escritos correctamente en la secuencia que, de todos modos, no están almacenados en este momento. Pero un archivo que no está cerrado no vive para siempre, en cambio FileOutputStream tiene
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();
}
}
}
Si no cierra un archivo, se cierra de todos modos, solo que no inmediatamente (y como dije, los datos que quedan en un búfer se perderán de esta manera, pero no hay ninguno en este momento)
¿Cuál es la consecuencia de no cerrar el archivo de inmediato? En condiciones normales, puede perder algunos datos y quedarse sin descriptores de archivo. Pero si tiene un sistema donde puede crear archivos pero no puede escribirles nada, tiene un problema mayor. es decir, es difícil imaginar por qué intenta repetidamente crear este archivo a pesar del hecho de que está fallando.
Tanto OutputStreamWriter como BufferedWriter no lanzan IOException en sus constructores, por lo que no está claro qué problema causarían. En el caso de BufferedWriter, puede obtener un OutOfMemoryError. En este caso, activará inmediatamente un GC, que como hemos visto cerrará el archivo de todos modos.