在Java中,当我调用OutputStream.close()时是否总是需要先调用OutputStream.flush()?
如果我只是在输出stream中调用close()
,输出是有保证的,或者需要我总是调用flush()
。
closures()总是刷新,所以不需要调用。
编辑:这个答案是基于常识和我遇到的所有输出stream。 谁将实现一个缓冲stream的close()而不首先刷新缓冲区? close()之前调用flush是没有害处的。 但是,如果flush()被过度调用,会有后果。 它可能会在缓冲机制下失败。
虽然close
应该调用flush
,但比这更复杂一点…
首先,装饰器(如BufferedOutputStream
)在Java中很常见。 装饰器的构造可能会失败,所以你需要close
包含装饰器的finally
块中的“raw”stream。 在出现exception的情况下,通常不需要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成语来保持干爽(ish)。
如果你希望stream被刷新,那么是的 ,在调用close()
之前调用flush()
close()
。
尽pipe所有其他答案相反(但正如在一些注释中注明的那样), java.io.OutputStream::close()
的默认实现不会调用flush()
。 事实上,它什么都不做。 如果你有一个源代码发行版,你可以很容易地自己检查一下,否则只要相信官方的javadoc ,在这里引用:
closures的总体合同是closures输出stream。 封闭的stream不能执行输出操作,不能重新打开。
OutputStream的close方法什么都不做。
无论close()
是否刷新,最安全的方法应该是手动刷新。 如果它再次被刷新,谁在乎?
“Tom Hawtin – tackline”的答案有关于安全closuresstream的更多细节(但是并没有真正地回答原来的问题= P)。
这里有很多危险的答案和评论。 请继续阅读为什么我用危险这个词。
首先是事情。 检查出来。
-
AutoCloseable#close()
-
Closeable#close()
-
OutputStream#close()
Writer#close()
你会发现没有任何单一的声明说close()
会调用flush()
。 修理我,如果我错过了任何。
使用flush()
需要时或需要保证缓冲的数据至less被刷新到操作系统级别。
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()
明确表示说
closures小溪,首先冲洗它。
但这并不意味着所有的子类都保留这个根合同。 参见PrintWriter#close()
which(without flush()
)closures内部out
( Writer
),同样依赖于out
的close()
实现。
stream表示通过调用close方法必须始终清除的资源。 一些java.io类(显然只是输出类)包含一个flush方法。 当在这样的类上调用close方法时,它会自动执行刷新。 调用close之前不需要显式调用flush 。