【问题标题】:Use try-with-resources or close this "BufferedReader" in a "finally" clause使用 try-with-resources 或在“finally”子句中关闭此“BufferedReader”
【发布时间】:2019-05-15 13:55:50
【问题描述】:

一直在寻找解决此问题的方法。阅读所有以前的答案,但没有一个帮助我。 SonarQube 会不会有什么错误?

public class Br {

    public String loader(String FilePath){

        BufferedReader br;
        String str = null;
        StringBuilder strb = new StringBuilder();
        try {
            br = new BufferedReader(new FileReader(FilePath));
            while ((str = br.readLine()) != null) {
                strb.append(str).append("\n");
            }
        } catch (FileNotFoundException f){
            System.out.println(FilePath+" does not exist");
            return null;
        } catch (IOException e) {
            e.printStackTrace();
        }
        return strb.toString();
    }
}

【问题讨论】:

  • 运行代码 100 万次。你会看到你已经创建了一个资源泄漏。您正在打开资源,但从不关闭它们
  • 您缺少br.close() 方法以防止资源泄漏。这可以在catch 块之后的finally 块或try (BufferedReader br = new BufferedReader(new FileReader(FilePath))) { .... 中实现
  • 试了你说的,还是报错。
  • 始终默认使用 try-with-resources。
  • 根本没有帮助。尝试了所有建议的方法仍然有很多其他错误。如果我尝试添加 finally{} ,我会得到 "br was not initialized" 。在我将 br 设置为 null 后,我最终会出现其他错误等等。

标签: java try-catch bufferedreader


【解决方案1】:

您没有调用br.close(),这意味着冒着资源泄漏的风险。为了可靠地关闭BufferedReader,您有两种选择:

使用finally 块:

public String loader(String FilePath) {
    // initialize the reader with null
    BufferedReader br = null;
    String str = null;
    StringBuilder strb = new StringBuilder();

    try {
        // really initialize it inside the try block
        br = new BufferedReader(new FileReader(FilePath));
        while ((str = br.readLine()) != null) {
            strb.append(str).append("\n");
        }
    } catch (FileNotFoundException f) {
        System.out.println(FilePath + " does not exist");
        return null;
    } catch (IOException e) {
        e.printStackTrace();
    } finally {
        // this block will be executed in every case, success or caught exception
        if (br != null) {
            // again, a resource is involved, so try-catch another time
            try {
                br.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    return strb.toString();
}

使用try-with-resources 声明:

public String loader(String FilePath) {
    String str = null;
    StringBuilder strb = new StringBuilder();

    // the following line means the try block takes care of closing the resource
    try (BufferedReader br = new BufferedReader(new FileReader(FilePath))) {
        while ((str = br.readLine()) != null) {
            strb.append(str).append("\n");
        }
    } catch (FileNotFoundException f) {
        System.out.println(FilePath + " does not exist");
        return null;
    } catch (IOException e) {
        e.printStackTrace();
    }

    return strb.toString();
}

【讨论】:

  • 好的,使用 finally 括号的方法效果很好!不知道为什么 try-with-resources 没有成功!非常感谢!
  • @Lol 不客气!那是经典版本。你试过另一个吗? SonarQube 抱怨过吗?如果它有帮助,请考虑接受答案,它也会给你一点声誉。
  • 第二个版本似乎不适合我!会给出和以前一样的错误。
  • @Lol 这很有趣......难道不是 SonarQube 本身声明了在“finally”子句中使用 try-with-resources 或关闭这个“BufferedReader”?您的问题的标题是错误消息,不是吗?
  • 是的!当尝试使用资源时,我最终得到了同样的声明,这完全是奇怪的。
【解决方案2】:

似乎您只想读取文件中的所有行。你可以使用这个:

public String loader(String FilePath) {
    try(Scanner s = new Scanner(new File(FilePath).useDelimiter("\\A")) {
        return s.hasNext() ? s.next() : null;
    } catch(IOException e) {
        throw new UncheckedIOException(e);
    }
}

【讨论】:

    【解决方案3】:

    您编写的代码确实在泄漏资源,因为您没有关闭 BufferedReader。以下 sn-p 应该可以解决问题:

    public String loader(String filePath){
        String str = null;
        StringBuilder strb = new StringBuilder();
        // try-with-resources construct here which will automatically handle the close for you
        try (FileReader fileReader = new FileReader(filePath); 
             BufferedReader br = new BufferedReader(fileReader);){
            while ((str = br.readLine()) != null) {
                strb.append(str).append("\n");
            }
        }
        catch (FileNotFoundException f){
            System.out.println(filePath+" does not exist");
            return null;
        }
        catch (IOException e) {
            e.printStackTrace();
        }
        return strb.toString();
    }
    

    如果您对此代码仍有问题,那么是的,这是 SonarQubes 的错误 :-)

    【讨论】:

    • 哦,好吧,那就是 SonarQubes 错误!之前尝试过。现在再试一次,仍然出现同样的错误。谢谢!
    • 也许是一个长镜头,但也许 SonarQube 需要在 try-with-resources 构造中分别声明 FileReader 和 BufferedReader?在此基础上调整了我的样本。
    猜你喜欢
    • 2021-10-08
    • 2021-02-14
    • 1970-01-01
    • 2019-03-31
    • 1970-01-01
    • 2021-12-14
    • 2020-05-13
    • 2019-07-08
    • 1970-01-01
    相关资源
    最近更新 更多