Вы можете закрыть самый внешний поток, на самом деле вам не нужно сохранять все потоки в оболочке, и вы можете использовать Java 7 try-with-resources.
try (BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(
new GZIPOutputStream(new FileOutputStream(createdFile)))) {
// write to the buffered writer
}
Если вы подписаны на YAGNI или вам это не понадобится, вам следует добавлять только тот код, который вам действительно нужен. Вы не должны добавлять код, который, по вашему мнению, может вам понадобиться, но на самом деле не делает ничего полезного.
Возьмите этот пример и представьте, что могло бы пойти не так, если бы вы этого не сделали, и каковы будут последствия?
try (
OutputStream outputStream = new FileOutputStream(createdFile);
GZIPOutputStream gzipOutputStream = new GZIPOutputStream(outputStream);
OutputStreamWriter osw = new OutputStreamWriter(gzipOutputStream);
BufferedWriter bw = new BufferedWriter(osw)
) {
// ...
}
Начнем с FileOutputStream, который open
выполняет всю реальную работу.
/**
* 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;
Если файл не найден, значит, нет базового ресурса, который нужно закрыть, поэтому его закрытие не имеет никакого значения. Если файл существует, он должен генерировать исключение FileNotFoundException. Таким образом, попытка закрыть ресурс только в этой строке ничего не даст.
Причина, по которой вам нужно закрыть файл, - это когда файл открывается успешно, но позже вы получаете сообщение об ошибке.
Давайте посмотрим на следующий поток GZIPOutputStream
Есть код, который может вызвать исключение
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)
});
}
Это записывает заголовок файла. Для вас было бы очень необычно иметь возможность открыть файл для записи, но не иметь возможности записать в него даже 8 байтов, но давайте представим, что это может произойти, и мы не закрываем файл после этого. Что произойдет с файлом, если он не закрыт?
Вы не получаете незаполненных записей, они отбрасываются, и в этом случае нет успешно записанных байтов в поток, который в любом случае не буферизуется в этот момент. Но файл, который не закрыт, не живет вечно, вместо этого 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();
}
}
}
Если вы вообще не закрываете файл, он все равно закрывается, но не сразу (и, как я уже сказал, данные, оставшиеся в буфере, будут потеряны таким образом, но на данный момент их нет)
Каковы последствия немедленного закрытия файла? В нормальных условиях вы потенциально теряете некоторые данные и потенциально можете исчерпать файловые дескрипторы. Но если у вас есть система, в которой вы можете создавать файлы, но не можете в них ничего писать, у вас есть большая проблема. т.е. трудно представить, почему вы неоднократно пытаетесь создать этот файл, несмотря на то, что у вас ничего не получается.
И OutputStreamWriter, и BufferedWriter не генерируют исключение IOException в своих конструкторах, поэтому неясно, какую проблему они могут вызвать. В случае BufferedWriter вы можете получить OutOfMemoryError. В этом случае он немедленно запустит сборщик мусора, который, как мы видели, в любом случае закроет файл.