19

乍一看,这段代码似乎完全没问题

BufferedOutputStream bout = new BufferedOutputStream(new FileOutputStream("1.txt"));
byte[] bytes = new byte[4096];
bout.write(bytes);
bout.close();

但如果我们仔细看看,我们会看到它close()的实现如下

public void close() throws IOException {
    try {
      flush();
    } catch (IOException ignored) {
    }
    out.close();
}

是否有可能由于flush()错误被忽略,数据可能会丢失而程序不会注意到它?没有提及FilterOutputStream.close(从哪里BufferedOutputStream继承close())API 中的任何危险。

更新:为了模拟 close() 期间的 IO 错误,我将测试更改为写入闪存,在 bout.close() 之前添加了 5 秒睡眠,当测试处于睡眠状态时,我从 USB 中移除了闪存。测试无一例外地完成,但是当我插入 Flash 并检查它时 - 1.txt 不存在。

然后我覆盖了 close()

    BufferedOutputStream bout = new BufferedOutputStream(new FileOutputStream("g:/1.txt")) {
        @Override
        public void close() throws IOException {
            flush();
            super.close();
        }
    };

并再次运行测试并得到

Exception in thread "main" java.io.FileNotFoundException: g:\1.txt (The system cannot the specified path)
    at java.io.FileOutputStream.open(Native Method)
    at java.io.FileOutputStream.<init>(FileOutputStream.java:212)
    at java.io.FileOutputStream.<init>(FileOutputStream.java:104)
    at test.Test1.main(Test1.java:10)
4

1 回答 1

6

事实上,我认为调用close确实会让你丢失数据,因为这种潜力IOException被默默地忽略了(谁知道开发人员的想法是什么......)。

一个不错的选择,虽然它确实把精力放在了程序员的一边,是在flush之前显式调用close(正确处理潜在的IOException),就像@Tom 的评论中提到的那样,特别是在一个try/finally块中。

由于AutoCloseable对象的原因,Java7 中这个问题可能会进一步恶化,因为您不会显式调用该close()方法,而且这种变通方法更容易被忽略。

于 2013-01-23T11:17:48.117 回答