Eclipse警告潜在的资源泄漏虽然我有一个关闭最外层流的finally块,但我错过了什么?

Ski*_*zoa 1 java eclipse streamreader resource-leak

有没有一个原因Eclipse给我以下资源泄漏警告:资源泄漏:'br'永远不会关闭"?我正在谈论的代码是在这篇文章的底部.

我以为我的最后一块都被覆盖了,我的理由是:

  • 如果FileInputStream构造函数抛出,res将仅为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();
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

T.J*_*der 5

Eclipse可能只是不了解你正在使用res变量进行的改组.

我建议使用try-with-resources语句(在Java 7及更高版本中提供,现在已经有三年半了),它大大简化了这些类型的链:

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();
    }
}
Run Code Online (Sandbox Code Playgroud)

如果你不能使用try-with-resources,你可能想要类似Apache Commons IOUtils类的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);
    }
}
Run Code Online (Sandbox Code Playgroud)

注意我是如何使用普通closetry,但是确保在中清理finally.

但是,尝试使用资源是更好的答案,因为它更简洁并且与新的(ish)"抑制异常"内容挂钩.


旁注:没有理由进行= null初始化line,在下一行分配.

附注2:如果文件可能是任何大小,请考虑事先找出它有多大并设置StringBuilder构造函数中的容量.StringBuilder默认容量为16,因此即使是几百字节的文件也会涉及几次StringBuilder内部缓冲区的重新分配.