如果我只是close()在输出流中调用,输出是保证的,还是需要我flush()总是调用?
Tom*_*ine 23
虽然close应该打电话flush,但它比那复杂一点......
首先,装饰器(例如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();
}
Run Code Online (Sandbox Code Playgroud)
最重要的是,装饰器close方法通常不正确地实现.这包括一些java.io直到最近.
当然,你可能想要使用Execute Around习语来保持DRY(ish).
ZZ *_*der 22
关闭()总是刷新,所以不需要打电话.
编辑:这个答案是基于常识和我遇到的所有输出流.谁将为缓冲流实现close()而不先刷新缓冲区?在close()之前调用flush是没有害处的.但是,如果过度调用flush()会产生后果.它可能会在缓冲机制下失败.
如果您希望刷新流,则是,请flush()在调用之前调用close()。
尽管所有其他答案都相反(但正如某些评论中正确指出的那样), 的默认实现java.io.OutputStream::close() 不会调用flush(). 事实上,它什么都不做。如果您有源代码发行版,您可以自己轻松查看,否则只需相信官方 javadoc,引用此处:
close 的一般约定是它关闭输出流。关闭的流无法执行输出操作,也无法重新打开。
OutputStream 的 close 方法什么也不做。
不管是否close()冲水,最安全的做法应该是手动冲水。如果它再次发红,谁在乎?
“Tom Hawtin-tackline”的答案有关于安全关闭流的额外细节(但并没有真正清楚地回答原始问题=P)。
这里有很多危险的答案和评论。继续阅读我为什么使用危险这个词。
先说第一件事。检查这些。
你会发现没有一个语句是 say close()will call flush()。如果我错过了,请修复我。
使用flush()时,你需要或者必须保证缓存数据刷新至少到操作系统级别。
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?
}
Run Code Online (Sandbox Code Playgroud)
事情可能已经改变了,但我在大约十年前亲身经历过。上面的源代码(客户端)在 Windows XP 上工作,但在 Windows 2000 Server 上失败,用于同一端点(服务器)。
并且(您)不必(必须)依赖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?
}
}
Run Code Online (Sandbox Code Playgroud)
另请注意,这flush()并不意味着将数据写入/发送到物理磁盘或远程端点。大多数情况下,它只是将 JVM 中的缓冲数据刷新到底层操作系统中。
勘误表
Writer#close() 明确表示它
关闭流,首先冲洗它。
但这并不意味着所有子类都保留这个根契约。看看PrintWriter#close()哪个(没有flush())关闭了内部out(Writer),这又取决于一个out的close()实现。
| 归档时间: |
|
| 查看次数: |
25530 次 |
| 最近记录: |