在 Java 中,当我调用 OutputStream.close() 时,是否总是需要先调用 OutputStream.flush()?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2732260/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
In Java, when I call OutputStream.close() do I always need to call OutputStream.flush() before?
提问by Tom Brito
If I just call close()
in a output stream, the output is guaranteed, or need I call flush()
always?
如果我只是close()
在输出流中调用,输出是有保证的,还是需要我flush()
总是调用?
采纳答案by ZZ Coder
Close() always flushes so no need to call.
Close() 总是刷新所以不需要调用。
EDIT: This answer is based on common sense and all the outputstream I encountered. Who is going to implement a close() for a buffered stream without flushing buffer first? There is no harm to call flush right before close(). However, there are consequences if flush() is called excessively. It may defeat underneath buffering mechanism.
编辑:这个答案基于常识和我遇到的所有输出流。谁将在不先刷新缓冲区的情况下为缓冲流实现 close() ?在 close() 之前调用 flush 没有害处。但是,如果过度调用flush() 会产生后果。它可能会破坏底层缓冲机制。
回答by Tom Hawtin - tackline
Whilst close
should call flush
, it's a bit more complicated than that...
虽然close
应该调用flush
,但它比那要复杂一些......
Firstly, decorators (such as BufferedOutputStream
) are common in Java. Construction of the decorator may fail, so you need to close
the "raw" stream in a finally
block whose try
includes the decorator. In the case of an exception, you don't usually need to close
the decorator (except, for instance, for badly implemented compression decorators). You do typically need to flush
the decorator in the non-exception case. Therefore:
首先,装饰器(例如BufferedOutputStream
)在 Java 中很常见。装饰器的构建可能会失败,因此您需要close
在包含装饰器的finally
块中创建“原始”流try
。在出现异常的情况下,您通常不需要close
装饰器(例如,对于实现不良的压缩装饰器除外)。flush
在非异常情况下,您通常需要装饰器。所以:
final RawOutputStream rawOut = new RawOutputStream(rawThing);
try {
final DecoratedOutputStream out = new DecoratedOutputStream(rawOut);
// ... stuff with out within ...
out.flush();
} finally {
rawOut.close();
}
To top it, decorator close
methods are often implemented incorrectly. That includes some in java.io
until recently.
最重要的是,装饰器close
方法经常被错误地实现。这包括一些java.io
直到最近。
Of course, you probably want to use the Execute Around idiom to keep in DRY(ish).
当然,您可能希望使用 Execute Around 成语来保持 DRY(ish)。
回答by brianmearns
If you want the stream to be flushed, then yes, call flush()
before calling close()
.
如果您希望刷新流,则是,请flush()
在调用之前调用close()
。
Despite all the other answers to the contrary (but as noted correctly in some comments), the default implementation of java.io.OutputStream::close()
does notcall flush()
. In fact, it does nothing. If you have a source distribution, you can easily check it out for yourself, otherwise just trust the official javadoc, quoted here:
尽管所有其他答案都相反(但正如某些评论中正确指出的那样), 的默认实现java.io.OutputStream::close()
不会调用flush()
. 事实上,它什么都不做。如果您有源代码发行版,您可以自己轻松查看,否则只需相信官方 javadoc,引用此处:
The general contract of close is that it closes the output stream. A closed stream cannot perform output operations and cannot be reopened.
The close method of OutputStream does nothing.
close 的一般约定是它关闭输出流。关闭的流无法执行输出操作,也无法重新打开。
OutputStream 的 close 方法什么也不做。
Regardless of whether close()
flushes or not, the safest approach should be to flush it manually. If it gets flushed again, who cares?
不管是否close()
冲水,最安全的做法应该是手动冲水。如果它再次发红,谁在乎?
The answer by "Tom Hawtin - tackline" has additional details on safely closing streams (but doesn't really answer the original question clearly =P).
“Tom Hawtin-tackline”的答案有关于安全关闭流的额外细节(但并没有真正清楚地回答原始问题=P)。
回答by Jin Kwon
There are so many dangerous answers and comments here. Keep read why I used the word dangerous.
这里有很多危险的答案和评论。继续阅读我为什么使用危险这个词。
First things first. Check these out.
先说第一件事。检查这些。
You shall find that there is no single statement that saying close()
will call flush()
. Fix me if I missed any.
你会发现没有一个语句是 say close()
will call flush()
。如果我错过了,请修复我。
Use flush()
whenever you need to or need to guarantee the buffered data flushed at least into OS level.
使用flush()
时,你需要或者必须保证缓存数据刷新至少到操作系统级别。
flush()
has its own purpose(s).
flush()
有自己的目的。
// client
// sends exactly 234 bytes
// and returns exactly 124 bytes from the server
static byte[] sendAndReceive(final OutputStream output,
final InputStream input)
throws IOException {
final byte[] request = new byte[234];
output.write(request);
// output.flush(); // @@? is this required or not?
final byte[] response = new byte[124];
new DataInputStream(input).readFully(response);
return response;
}
// server
// recieve exactly 234 bytes from the client
// sends exactly 124 bytes
static void receiveAndSend(final InputStream input,
final OutputStream output)
throws IOException {
final byte[] request = new byte[234];
new DataInputStream(input).readFully(request);
final byte[] response = new byte[124];
output.write(response);
// output.flush(); // @@? is this required or not?
}
Things might have been changed, but I experienced for myself about a decade ago. Above source code (client) worked with Windows XP and failed with Windows 2000 Server for a same endpoint(server).
事情可能已经改变了,但我在大约十年前亲身经历过。上面的源代码(客户端)在 Windows XP 上工作,但在 Windows 2000 Server 上失败,用于同一端点(服务器)。
And (you) do not (have to) rely on any implementation specific behaviour of close()
.
并且(您)不必(必须)依赖close()
.
static void writeFile(File file, byte[] bytes) throws IOException {
try (OutputStream out = new FileOutputStream(bytes)) {
out.write(bytes);
out.flush(); // who cares what FileInputStream#close does?
}
}
Note, also, that the flush()
doesn't mean to writing/sending your data to physical disk or remote endpoint. It, mostly, just flushes the buffered data in the JVM into the underlying OS.
另请注意,这flush()
并不意味着将数据写入/发送到物理磁盘或远程端点。大多数情况下,它只是将 JVM 中的缓冲数据刷新到底层操作系统中。
errata
勘误表
Writer#close()
explicitly says that it
Writer#close()
明确表示它
closes the stream, flushing it first.
关闭流,首先冲洗它。
But it doesn't mean all subclasses keep this root contract. See PrintWriter#close()
which (without flush()
) closes the internal out
(Writer
) which, again, depends one the out
's close()
implementation.
但这并不意味着所有子类都保留这个根契约。看看PrintWriter#close()
哪个(没有flush()
)关闭了内部out
(Writer
),这又取决于一个out
的close()
实现。