1

Eclipse が次のリソース リーク警告を表示する理由はありますか:リソース リーク: 'br' は決して閉じられません" ? 私が話しているコードは、この投稿の下部にあります。

私の最終ブロックはそれをすべてカバーしていると思いました、私の推論:

  • res は、 FileInputStream コンストラクターがスローした場合にのみ null になるため、何も閉じる必要はありません
  • InputStreamReader コンストラクターがスローする場合 (たとえば、不正な形式のエンコーディング文字列)、res が入力ストリームになり、InputStream のみを閉じる必要があるため、問題ありません。
  • 等...

それで、私は何が欠けていますか?それとも、これは日食のバグでしょうか?

敬具!

S.

public static String fileToString(String fileName, String encoding) throws IOException {
    InputStream is;
    InputStreamReader isr;
    BufferedReader br;
    Closeable res = null;
    try {
        is = new FileInputStream(fileName);
        res = is;
        isr = new InputStreamReader(is, encoding);
        res = isr;
        br = new BufferedReader(isr);
        res = br;
        StringBuilder builder = new StringBuilder();
        String line = null;
        while ((line = br.readLine()) != null) {
            builder.append(line);
            builder.append(LS);
        }
        return builder.toString();
    } finally {
        if (res != null) {
            res.close();
        }
    }
}
4

1 に答える 1

5

Eclipse はおそらく、res変数で行っているシャッフルを理解していないだけです。

try-with-resources ステートメントを使用することをお勧めします (Java 7 以降で利用可能で、現在 3 年半使用されています)。これにより、これらの種類のチェーンが劇的に簡素化されます。

public static String fileToString(String fileName, String encoding) throws IOException {

    try (
        InputStream is = new FileInputStream(fileName);
        InputStreamReader isr = new InputStreamReader(is, encoding);
        BufferedReader br = new BufferedReader(isr)
    ) {
        StringBuilder builder = new StringBuilder();
        String line = null;
        while ((line = br.readLine()) != null) {
            builder.append(line);
            builder.append(LS);
        }
        return builder.toString();
    }
}

try-with-resources を使用できない場合は、おそらく、Apache CommonsIOUtilsクラスのcloseQuietlyメソッド(文字通りそのメソッドまたは独自のメソッドのいずれか)のようなものが必要になるでしょうres

を使用IOUtilsすると、次のようになります。

public static String fileToString(String fileName, String encoding) throws IOException {
    InputStream is = null;
    InputStreamReader isr = null;
    BufferedReader br = null;

    try {
        is = new FileInputStream(fileName);
        isr = new InputStreamReader(is, encoding);
        br = new BufferedReader(isr)
        StringBuilder builder = new StringBuilder();
        String line = null;
        while ((line = br.readLine()) != null) {
            builder.append(line);
            builder.append(LS);
        }
        br.close();
        return builder.toString();
    }
    finally {
        IOUtils.closeQuietly(br, isr, is);
    }
}

で法線を使用する方法に注意してくださいclosetryただし、 で確実にクリーンアップしてfinallyください。

しかし、try-with-resources の方がより簡潔で、新しい (ish) 「抑制された例外」のものにフックされるため、より良い答えです。


補足: を= null初期化する理由はありませんline。次の行に割り当てます。

補足 2: ファイルが任意のサイズになる可能性がある場合は、事前にサイズを確認StringBuilderし、コンストラクターでの容量を設定することを検討してください。StringBuilderのデフォルトの容量は 16 であるため、数百バイトのファイルであっても、StringBuilderの内部バッファの再割り当てが数回行われます。

于 2014-11-27T15:15:15.373 に答える