3

Findbugsは、2つのCloseableインスタンスを開くメソッドについて私を悩ませていますが、その理由がわかりません。

ソース

public static void sourceXmlToBeautifiedXml(File input, File output)
        throws TransformerException, IOException, JAXBException {

    FileReader fileReader = new FileReader(input);
    FileWriter fileWriter = new FileWriter(output);

    try {
        // may throw something
        sourceXmlToBeautifiedXml(fileReader, fileWriter);
    } finally {
        try {
            fileReader.close();
        } finally {
            fileWriter.close();
        }
    }
}

Findbugsの分析

Findbugsは私に教えてくれます

Method [...] may fail to clean up java.io.Reader [...]

との線を指すFileReader fileReader = ...

質問

誰が間違っていますか:私またはFindbugs?

4

4 に答える 4

4

FindBugs は正しいです。FileWriter のコンストラクターが例外をスローした場合、ファイル リーダーは閉じられません。これを確認するには、無効なファイル名を渡してみてくださいoutput

私は次のようにします:

    FileReader fileReader = new FileReader(input);

    try {
        FileWriter fileWriter = new FileWriter(output);
        try {
            // may throw something
            sourceXmlToBeautifiedXml(fileReader, fileWriter);
        } finally {
            fileWriter.close();
        }
    } finally {
        fileReader.close();
    }

例外をスローしてfinallyブロックを離れると、その例外をスローしてtryステートメントが終了し、tryブロックでスローされた例外を飲み込むため、閉じるときにスローされる例外の処理が改善される可能性があることに注意してください。デバッグにより便利です。これを回避する簡単な方法については、duffymo の回答を参照してください。

編集:Java 7以降、try-with-resourcesステートメントを使用できるようになりました。これにより、これらのコーナーケースを正しく簡潔に処理できます。

try (
    FileReader fileReader = new FileReader(input); 
    FileWriter fileWriter = new FileWriter(output)
) {
    // may throw something
    sourceXmlToBeautifiedXml(fileReader, fileWriter);
}
于 2010-03-14T14:41:45.710 に答える
3

これは、findbugs にとっても複雑な場合があります。

try {
   fileReader.close();
} finally {
   fileWriter.close();
}

私にはあなたが正しいようです。

編集:うわー、私はfindbugsが間違っている可能性があると言って投票されると思っていました!

編集:FindBugsは結局正しいようです。よく釣れるメリットン。

于 2010-03-14T10:58:46.090 に答える
0

あなただと思います。

別の try/catch ブロックで両方のリソースを閉じます。私は私を助けるために静的メソッドを作成します:

public static void sourceXmlToBeautifiedXml(File input, File output)
        throws TransformerException, IOException, JAXBException {

    FileReader fileReader = new FileReader(input);
    FileWriter fileWriter = new FileWriter(output);

    try {
        // may throw something
        sourceXmlToBeautifiedXml(fileReader, fileWriter);
    } finally {
        close(fileReader);
        close(fileWriter);
    }
}


// same for reader & writer
public static void close(InputStream s)
{
    try
    { 
       if (s != null)
       {
           s.close();
       }
    }
    catch (IOException e)
    {
        e.printStackTrace();
    }
}
于 2010-03-14T10:50:51.883 に答える
-1

私はfindbugsが正しいと思います。

} finally {
    try {
        fileReader.close();
    } finally {
        fileWriter.close();
    }
}

このブロックでは、FileReader を閉じようとします。ただし、これは例外をスローする可能性があり、ネストされた最終的には fileWriter を閉じます。同じfinallyブロックで両方のリーダーを閉じようとしましたか? では、findbugs は何と言っているでしょうか。

} finally {
    try {
        fileReader.close();
        fileWriter.close();
    } finally {
        //dunno maybe log that something went wrong.
    }
}
于 2010-03-14T10:49:05.470 に答える