4

假设我有以下代码片段:

operation1();
bw.close();
operation2();

当我BufferedReader.close()从我的代码中调用时,我假设我的 JVM 进行了系统调用,以确保缓冲区已被刷新并写入磁盘。我想知道是close()等待系统调用完成其操作还是继续进行operation2()而不等待close()完成。

重新表述我的问题,当我这样做时operation2(),我可以假设bw.close()已经成功完成了吗?

4

8 回答 8

5

当我执行 operation2() 时,我可以假设 bw.close() 已成功完成吗?

是的

于 2010-06-02T18:30:01.473 回答
4

关闭流,先冲洗它。关闭流后,进一步的 write() 或 flush() 调用将导致抛出 IOException。但是,关闭先前关闭的流没有任何效果。

尽管文档没有具体说明,但我认为此调用会阻塞直到完成。事实上,我很确定java.io包中的任何内容都不是非阻塞的。

于 2010-06-02T18:28:56.107 回答
4

如果java.io.BufferedReader.close()java.io.Reader.

医生说:

关闭流并释放与其关联的任何系统资源。关闭流后,进一步的 read()、ready()、mark()、reset() 或 skip() 调用将引发 IOException。关闭以前关闭的流没有效果。

虽然这在文件系统完成之前没有明确声明阻塞,但如果返回,BufferedReader所有其他操作的相同实例将引发异常。close()尽管 JavaDoc 对于操作何时完成可能会被视为模棱两可,但如果在此方法返回时文件系统刷新和关闭未完成,则将违反合同精神并成为 Java 中的错误(实现或文档)。

于 2010-06-02T18:35:59.977 回答
2

不!您无法确定,原因如下:

BufferedWriter 是另一个 Writer 的包装器。BufferedWriter 的 close() 只会传播到底层 Writer。

如果这个底层 Writer 是一个 OutputStreamWriter,并且如果 OutputStream 是一个 FileOutputStream,那么 close 将发出一个系统调用来关闭文件句柄。

您甚至可以完全自由地拥有一个 Writer,其中 close() 是一个 noop,或者 close 是非阻塞实现的,但是当仅使用 java.io 中的类时,情况绝不会如此。

于 2010-06-02T18:38:27.450 回答
1

A Writer(或BufferedWriter)是一个黑匣子,它在某处写入字符流,不一定写入磁盘。对must的调用(通过方法契约)在关闭之前刷新其缓冲内容,并且应该(通常)在其所有“基本”工作完成之前阻塞。但这取决于实现和环境(例如,您无法了解 Java 层以下的缓存)。在 Java 编写器本身要完成的工作的哪些方面(例如:在 FileWriter 或类似的情况下进行系统调用以写入磁盘,并关闭文件句柄),是的,您可以假设当返回它时已经完成了所有工作。close() close()

于 2010-06-02T18:34:12.813 回答
1

通常,对于任何 i/o 操作,您都不能对操作完成后发生的情况做出任何假设write(),即使在您close. 的概念delivery是相对于媒介的主观概念。

例如,如果writer代表一个 TCP 连接,然后数据在客户端和服务器之间丢失了怎么办?或者如果内核将数据写入磁盘,但驱动器在物理上无法写入数据怎么办?或者,如果作者代表一只在途中被击中的信鸽?

此外,想象一下写入无法确认端点已收到数据的情况(读取:udp/datagrams)。在那种情况下,阻塞策略应该是什么?

于 2010-06-02T18:47:46.123 回答
1

缓冲区将被刷新到操作系统并关闭文件句柄,因此所需的 Java 操作将已完成。

但是操作系统会将写入缓存或排队到实际的磁盘、管道、网络等等——不能保证物理写入已经完成。FileChannel.force() 为本地磁盘上的文件提供了一种方法:请参阅 Javadoc。

于 2010-06-03T00:05:38.077 回答
0

是的,如果您到达operation2();,则必须完全关闭流。但是,close() throws IOException,因此您甚至可能无法到达operation2();. 这可能是也可能不是您所期望的行为。

于 2010-06-02T18:30:28.227 回答