【问题标题】:How to solve failure to close a FileStream如何解决无法关闭 FileStream
【发布时间】:2018-09-07 21:34:52
【问题描述】:

我已经在 try/finally 中关闭了文件 steam,但代码分析警告我:

  • 可能无法关闭 FileOutputStream
  • 可能无法关闭 PrintWriter
  • 可能无法关闭 OutputStreamWriter

失败怎么会发生?如何确保 FileStream 已关闭?

public void writeFile(String filepath)
{
    BufferedWriter bw = null;
    PrintWriter pw = null;
    try {
        File file = new File(filepath);
        bfw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file), "UTF-8"));
        pw = new PrintWriter(bfw);

     //do something

    }catch(Exception e){
        e.printStackTrace();
    }
    finally{
        try{
            bfw.close();
            pw.close();
        }catch(Exception e){
            e.printStackTrace();
        }
    }
}

【问题讨论】:

    标签: java filestream resource-leak


    【解决方案1】:

    如果您使用Java-7 及以上,则可以使用try with resources

    File file = new File(filepath);
    try(BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file), "UTF-8"));
        PrintWriter pw = new PrintWriter(bfw);)
    {
        ...
    }
    catch(Exception exception) //This is optional
    {
        exception.printStackTrace();
    }
    

    您可以像普通的 try 语句一样使用带有 try-with-resources 语句的 catch 和 finally 块。

    希望这会有所帮助!

    【讨论】:

    • 你可以省略 catch 和 finally 块,因为隐式 finally 已经存在。
    【解决方案2】:

    如果关闭 bw 时发生异常,您将不会关闭 pw。试试这个:

    finally{
        try{
            bw.close();
        } catch(Exception e){
            e.printStackTrace();
        } finally {
            pw.close();
        }
    }
    

    【讨论】:

    • 事实上 pw.close() 在内部关闭了底层流 - bw。最佳解决方案(java 7 除外)是: pw = new PrintWriter(new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file), "UTF-8")));
    【解决方案3】:

    失败怎么会发生?

    查看你的 finally 块:

    finally{
        try{
            bfw.close();   <== exception occured here
            pw.close();    <== this is not execute
        }catch(Exception e){
            e.printStackTrace();
        }
    }
    

    如果bfw.close()出现异常怎么办? pw.close() 永远不会执行。这会导致资源泄漏。

    如何确保 FileStream 已关闭?

    有人已经指出在 finally 内部使用 try/catch/finally。 但如果你不喜欢看到这么多 try catch finally 我建议你使用像 Apache Commons IO 这样的库。

    解决方案:

    try {
    
       ........
    } finally {
        IOUtils.closeQuietly(bfw);
        IOUtils.closeQuietly(pw);
    }
    

    是的,如果使用 Java 7 或更高版本,您总是有 try-with-resources

    【讨论】:

    • 我认为 Am_I_Helpful 和 VedX 的混合是答案。最好在 close() 之前进行 null 检查,并在资源泄漏的情况下捕获 close() 中发生的每个异常。 VedX 是一个很好的答案,有明确的解释,但它不能处理异常情况。所以我选择这个作为答案
    • 您是否知道来自commons-ioIOUtils 存在公开的安全漏洞@tensor?
    猜你喜欢
    • 1970-01-01
    • 2015-10-18
    • 1970-01-01
    • 2021-07-26
    • 2019-03-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-04-21
    相关资源
    最近更新 更多