java - 尽管我有一个关闭最外层流的 finally block ,但 Eclipse 警告潜在的资源泄漏,我错过了什么?

标签 java eclipse streamreader resource-leak

Eclipse 给我以下资源泄漏警告是否有原因:Resource leak: 'br' is never closed"?我正在谈论的代码位于本文的底部。 p>

我认为我的 finally block 已经涵盖了所有内容,我的推理:

  • res 只有在 FileInputStream 构造函数抛出时才会为 null,因此无需关闭任何内容
  • 如果 InputStreamReader 构造函数抛出错误(例如格式错误的编码字符串),res 将是输入流,然后只有 InputStream 必须关闭,所以 ok
  • 等...

那我错过了什么?或者这可能是 eclipse 错误?

亲切的问候!

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();
        }
    }
}

最佳答案

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();
    }
}

如果您不能使用 try-with-resources,您可能需要类似 Apache Commons IOUtils 的东西类(class)的closeQuietly methods (从字面上看是那个,或者你自己的)而不是四处乱窜 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);
    }
}

请注意我如何在 try 中使用普通的 close,然后确保在 finally 中进行清理。

但 try-with-resources 是更好的答案,因为它更简洁并且与新的(ish)“抑制异常”内容 Hook 。


旁注:line= null 初始化没有任何原因,您在下一行分配它。

旁注 2:如果文件可能有任何大小,请考虑提前找出它有多大,并在构造函数中设置 StringBuilder 的容量。 StringBuilder 的默认容量为 16,因此即使是几百个字节的文件也需要多次重新分配 StringBuilder 的内部缓冲区。

关于java - 尽管我有一个关闭最外层流的 finally block ,但 Eclipse 警告潜在的资源泄漏,我错过了什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27173828/

相关文章:

java - 如何将两个不同大小的矩阵相乘

java - 如何在运行 jar 文件时创建文本文件

java - android中的 fatal error 异常

java - JTextField - 将边框重置为系统默认值

java - 注释声明中 String[] 的默认 ""是什么?

java - 如何从 TimePicker 创建两个时间值(currentHour 和 currentMinute),然后将它们连接在一起

c# - 从文本文件读取并返回数据(C#)

java - 此类问题的模式

Powershell 标准输出缓冲区对于外部命令来说太小

java - 写入 Avro 文件时架构更新