web-dev-qa-db-ja.com

Apache commons-io IOUtils.closeQuietlyを使用しても安全ですか?

このコードは

    BufferedWriter bw = new BufferedWriter(new FileWriter("test.txt"));
    try {
        bw.write("test");
    } finally {
        IOUtils.closeQuietly(bw);
    }

安全かどうか? BufferedWriterを閉じるとき、私が理解する限り、そのバッファーを基になるストリームにフラッシュし、エラーのために失敗する可能性があります。しかし、IOUtils.closeQuietly APIは、例外は無視されると述べています。

IOUtils.closeQuietlyが原因でデータ損失が気付かれない可能性はありますか?

34

closeQuietly()のjavadocに関して、コードは次のようになります。

_BufferedWriter bw = null;

try {
    bw = new BufferedWriter(new FileWriter("test.txt"));
    bw.write("test");
    bw.flush(); // you can omit this if you don't care about errors while flushing
    bw.close(); // you can omit this if you don't care about errors while closing
} catch (IOException e) {
    // error handling (e.g. on flushing)
} finally {
    IOUtils.closeQuietly(bw);
}
_

closeQuietly()は、Closableでclose()を直接呼び出すのではなく、一般的な使用を目的としていません。その意図されたユースケースは、finally-block内のクローズを保証するためです-あなたが必要とするすべてのエラー処理は、その前に行われなければなりません。

つまり、close()またはflush()の呼び出し中に例外に対応する場合は、通常の方法で例外を処理する必要があります。 finallyブロックにcloseQuietly()を追加すると、閉じることが保証されます。フラッシュが失敗し、try-blockでcloseが呼び出されなかったとき。

38
Fabian Barney

書き込みがエラーなしで成功したかどうかをアプリケーションが気にしない限り、安全です。アプリケーションが書き込みエラーを処理する必要がある場合、 終了時にフラッシュされたバッファデータ が失われ、エラーが飲み込まれる可能性があるため、安全ではありません。

7
McDowell

理論的には可能ですが、close()が失敗するのを見たことはありません。通常、高速フェールとは、ファイルを開くなどの前のIO操作が最初に失敗することを意味します。IOExceptionsを無視しないクローズを記述できますが、 try/catchブロック内で失敗したものです。

あなたが望むのは次のようなものです(ほとんどの場合、これは過剰です)

try {
    // write to bw.
    bw.close(); // throw IOException if an error occurs.

} finally {
    // don't clobber a previous IOException
    IOUtils.closeQuietly(bw);
}
5
Peter Lawrey

はい。Java6以下でのみ使用しても安全です。 Java7から、ユーザー try-with-resource を使用する必要があります。

それはあなたが持っているボイラープレートコードの多くとIOUtils.closeQuietlyを使用する必要性を排除します。

今、あなたの例:

    BufferedWriter bw = new BufferedWriter(new FileWriter("test.txt"));
    try {
        bw.write("test");
    } finally {
        IOUtils.closeQuietly(bw);
    }

次のように記述できます。

   try (BufferedWriter bw = new BufferedWriter(new FileWriter("test.txt"))) {
       bw.write("test");
   }

Try-with-resourceアプローチを使用するには、リソースでJava 7。

また、try-with-resourceブロックにいくつかのリソースを含めることができます。それらは;で区切るだけです

   try (
       BufferedWriter bw1 = new BufferedWriter(new FileWriter("test1.txt"));
       BufferedWriter bw2 = new BufferedWriter(new FileWriter("test2.txt"))
   ) {
       // Do something useful with those 2 buffers!
   }   // bw1 and bw2 will be closed in any case
4
Johnny