在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内部outWriter ),同样依赖于outclose()实现。

stream表示通过调用close方法必须始终清除的资源。 一些java.io类(显然只是输出类)包含一个flush方法。 当在这样的类上调用close方法时,它会自动执行刷新。 调用close之前不需要显式调用flush