假设我有以下代码片段:
operation1();
bw.close();
operation2();
当我BufferedReader.close()
从我的代码中调用时,我假设我的 JVM 进行了系统调用,以确保缓冲区已被刷新并写入磁盘。我想知道是close()
等待系统调用完成其操作还是继续进行operation2()
而不等待close()
完成。
重新表述我的问题,当我这样做时operation2()
,我可以假设bw.close()
已经成功完成了吗?
假设我有以下代码片段:
operation1();
bw.close();
operation2();
当我BufferedReader.close()
从我的代码中调用时,我假设我的 JVM 进行了系统调用,以确保缓冲区已被刷新并写入磁盘。我想知道是close()
等待系统调用完成其操作还是继续进行operation2()
而不等待close()
完成。
重新表述我的问题,当我这样做时operation2()
,我可以假设bw.close()
已经成功完成了吗?
当我执行 operation2() 时,我可以假设 bw.close() 已成功完成吗?
是的
关闭流,先冲洗它。关闭流后,进一步的 write() 或 flush() 调用将导致抛出 IOException。但是,关闭先前关闭的流没有任何效果。
尽管文档没有具体说明,但我认为此调用会阻塞直到完成。事实上,我很确定java.io
包中的任何内容都不是非阻塞的。
如果java.io.BufferedReader.close()
用java.io.Reader
.
医生说:
关闭流并释放与其关联的任何系统资源。关闭流后,进一步的 read()、ready()、mark()、reset() 或 skip() 调用将引发 IOException。关闭以前关闭的流没有效果。
虽然这在文件系统完成之前没有明确声明阻塞,但如果返回,BufferedReader
所有其他操作的相同实例将引发异常。close()
尽管 JavaDoc 对于操作何时完成可能会被视为模棱两可,但如果在此方法返回时文件系统刷新和关闭未完成,则将违反合同精神并成为 Java 中的错误(实现或文档)。
不!您无法确定,原因如下:
BufferedWriter 是另一个 Writer 的包装器。BufferedWriter 的 close() 只会传播到底层 Writer。
如果这个底层 Writer 是一个 OutputStreamWriter,并且如果 OutputStream 是一个 FileOutputStream,那么 close 将发出一个系统调用来关闭文件句柄。
您甚至可以完全自由地拥有一个 Writer,其中 close() 是一个 noop,或者 close 是非阻塞实现的,但是当仅使用 java.io 中的类时,情况绝不会如此。
A Writer
(或BufferedWriter
)是一个黑匣子,它在某处写入字符流,不一定写入磁盘。对must的调用(通过方法契约)在关闭之前刷新其缓冲内容,并且应该(通常)在其所有“基本”工作完成之前阻塞。但这取决于实现和环境(例如,您无法了解 Java 层以下的缓存)。在 Java 编写器本身要完成的工作的哪些方面(例如:在 FileWriter 或类似的情况下进行系统调用以写入磁盘,并关闭文件句柄),是的,您可以假设当返回它时已经完成了所有工作。close()
close()
通常,对于任何 i/o 操作,您都不能对操作完成后发生的情况做出任何假设write()
,即使在您close
. 的概念delivery
是相对于媒介的主观概念。
例如,如果writer
代表一个 TCP 连接,然后数据在客户端和服务器之间丢失了怎么办?或者如果内核将数据写入磁盘,但驱动器在物理上无法写入数据怎么办?或者,如果作者代表一只在途中被击中的信鸽?
此外,想象一下写入无法确认端点已收到数据的情况(读取:udp/datagrams)。在那种情况下,阻塞策略应该是什么?
缓冲区将被刷新到操作系统并关闭文件句柄,因此所需的 Java 操作将已完成。
但是操作系统会将写入缓存或排队到实际的磁盘、管道、网络等等——不能保证物理写入已经完成。FileChannel.force() 为本地磁盘上的文件提供了一种方法:请参阅 Javadoc。
是的,如果您到达operation2();
,则必须完全关闭流。但是,close() throws IOException
,因此您甚至可能无法到达operation2();
. 这可能是也可能不是您所期望的行为。