如果我只是在输出流中调用close()
,输出是有保证的,还是需要我总是调用flush()
?
答案 0 :(得分:23)
虽然close
应该致电flush
,但这比那更复杂......
首先,装饰器(例如BufferedOutputStream
)在Java中很常见。装饰器的构造可能会失败,因此您需要close
finally
块中的{raw}流,其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();
}
最重要的是,装饰器close
方法经常被错误地实现。这包括java.io
中的一些直到最近。
当然,您可能希望使用Execute Around成语来保持DRY(ish)。
答案 1 :(得分:22)
关闭()总是刷新,所以不需要打电话。
编辑:这个答案是基于常识和我遇到的所有输出流。谁将为缓冲流实现close()而不先刷新缓冲区?在close()之前调用flush是没有害处的。但是,如果过度调用flush()会产生后果。它可能会在缓冲机制下失败。
答案 2 :(得分:4)
这里有很多危险的答案和评论。请继续阅读为什么我使用了 dangerous 这个词。
首先要做的事情。看看这些。
您会发现没有一条声明说close()
会致电flush()
。如果我错过任何一个,请修复我。
当您需要或需要保证至少刷新到OS级别的缓冲数据时,请使用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?
}
事情可能已经发生了变化,但十年前我亲身经历过。上面的源代码(客户端)与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?
}
}
另请注意,flush()
并不意味着将数据写入/发送到物理磁盘或远程端点。它主要是将JVM中的缓冲数据刷新到底层操作系统中。
<强>勘误表强>
Writer#close()
明确说明了
关闭流,先冲洗它。
但它并不意味着所有子类都保留此根合约。请参阅PrintWriter#close()
哪个(不flush()
)关闭内部out
(Writer
),这又取决于out
&#39; {{1}实施。
答案 3 :(得分:3)
如果您想要刷新流,然后是,请在致电JSON.stringify()
之前致电var stringifyMe = { tokenValue: '36151b9e-ad0d-49de-a14b-5461489c7065' };
var stringified = JSON.stringify(stringifyMe);
// stringified is now equal to the string {"tokenValue":"36151b9e-ad0d-49de-a14b-5461489c7065"}
。
尽管所有其他相反的答案(但在某些评论中正确指出),flush()
的默认实施不会调用close()
。事实上,它什么都不做。如果您有源代码分发,您可以自己轻松查看,否则只需信任official javadoc,引用此处:
close的一般合约是关闭输出流。一个 封闭流无法执行输出操作,无法重新打开。
OutputStream的close方法不执行任何操作。
无论java.io.OutputStream::close()
是否刷新,最安全的方法应该是手动刷新。如果它再次被冲洗,谁在乎呢?
Tom Hawtin的回答 - 强调&#34;有关于安全关闭流的其他详细信息(但没有明确地回答原始问题= P)。