您可以关闭最外面的流,实际上不需要保留所有已包装的流,并且可以使用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。在这种情况下,它将立即触发GC,正如我们已经看到的那样,它将始终关闭文件。