Вы можете закрыть внешний наиболее поток, на самом деле вам не нужно сохранять все потоки завернуты, и вы можете использовать Java 7 примерочных с-ресурсов.
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. В этом случае он немедленно вызовет GC, который, как мы видели, все равно закроет файл.
Для соответствующего устаревшего вопроса Java 6 см. Http://stackoverflow.com/questions/884007/best-way-to-close-nested-streams-in-java-6 – Raedwald
Обратите внимание, что ваш пример имеет ошибку, которая может привести к потере данных, поскольку вы закрываете потоки не в том порядке, в котором вы их открыли. При закрытии «BufferedWriter» может потребоваться записать * буферизованные * данные в базовый поток, который в вашем примере уже закрыт. Избежать этих проблем является еще одним преимуществом подходов * try-with-resource *, показанных в ответах. – Joe23