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()データが失われ、プログラムがそれに気付かない可能性はありますか?API FilterOutputStream.close(からBufferedOutputStream継承する場所)の危険性については言及されていません。close()

更新: close()中のIOエラーをシミュレートするために、フラッシュメモリに書き込むようにテストを変更し、bout.close()の前に5秒間のスリープを追加し、テストのスリープ中にUSBからフラッシュを削除しました。テストは例外なく終了しましたが、フラッシュを挿入して確認したところ、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(地球上で誰がそれを行うために開発者の心を通過したかを知っています...)。

まともな代替手段は、プログラマーの側に努力を払うものの、@ Tomによるコメントで言及されているように、特にブロックで、flush前に明示的に呼び出すclose(ポテンシャルを正しく処理する)ことです。IOExceptiontry/finally

この問題は、オブジェクトが原因でJava7でさらに悪化する可能性があります。これAutoCloseableは、メソッドを明示的に呼び出さずclose()、この種の回避策がさらに簡単になるためです。

于 2013-01-23T11:17:48.117 に答える