使用Apache commons-io IOUtils.close可以安全吗?

Evg*_*eev 34 java apache-commons apache-commons-io

这是代码

    BufferedWriter bw = new BufferedWriter(new FileWriter("test.txt"));
    try {
        bw.write("test");
    } finally {
        IOUtils.closeQuietly(bw);
    }
Run Code Online (Sandbox Code Playgroud)

安全与否?据我所知,当我们关闭BufferedWriter时,它会将其缓冲区刷新到底层流,并可能因错误而失败.但IOUtils.closeQuietly API表示将忽略任何异常.

由于IOUtils.closeQuietly,数据丢失是否有可能被忽视?

Fab*_*ney 38

对于javadoc,代码应如下所示closeQuietly():

BufferedWriter bw = null;

try {
    bw = new BufferedWriter(new FileWriter("test.txt"));
    bw.write("test");
    bw.flush(); // you can omit this if you don't care about errors while flushing
    bw.close(); // you can omit this if you don't care about errors while closing
} catch (IOException e) {
    // error handling (e.g. on flushing)
} finally {
    IOUtils.closeQuietly(bw);
}
Run Code Online (Sandbox Code Playgroud)

closeQuietly()不是一般用途,而是close()直接在Closable上调用.它的预期用例是确保最终块内部的关闭 - 所有错误处理都必须在此之前完成.

这意味着,如果您想在调用期间对异常做出反应,close()或者flush()您要以正常方式处理它.添加closeQuietly()finally块只能确保关闭,例如当刷新失败并且未在try-block中调用close时.

  • @EvgeniyDorofeev是的,只要你把`close()`留在那里.但是当你只关心刷新期间的异常而不是关闭时,你需要明确地在这里进行刷新.刚写了两个方法调用,使这个例子更具普遍性. (2认同)

McD*_*ell 7

只要您的应用程序不关心写入是否成功而没有错误,它是安全的.如果您的应用程序需要处理写入错误,则不安全,因为关闭时刷新的缓冲数据可能会丢失并且吞下错误.


Joh*_*nny 6

是的,使用它是安全的,但仅适用于Java6及更低版本。从Java7 开始,您应该使用try-with-resource

它将消除您拥有的大部分样板代码以及使用IOUtils.closeQuietly.

现在,你的例子:

    BufferedWriter bw = new BufferedWriter(new FileWriter("test.txt"));
    try {
        bw.write("test");
    } finally {
        IOUtils.closeQuietly(bw);
    }
Run Code Online (Sandbox Code Playgroud)

可以写成:

   try (BufferedWriter bw = new BufferedWriter(new FileWriter("test.txt"))) {
       bw.write("test");
   }
Run Code Online (Sandbox Code Playgroud)

需要注意的是,为了使用 try-with-resource 方法,您的资源需要实现 Java 7 中引入的名为 java.lang.AutoCloseable 的新接口。

此外,您可以在 try-with-resource 块中包含许多资源,只需将它们与 ;

   try (
       BufferedWriter bw1 = new BufferedWriter(new FileWriter("test1.txt"));
       BufferedWriter bw2 = new BufferedWriter(new FileWriter("test2.txt"))
   ) {
       // Do something useful with those 2 buffers!
   }   // bw1 and bw2 will be closed in any case
Run Code Online (Sandbox Code Playgroud)


Pet*_*rey 5

这在理论上是可能的,但我不能说我见过close()失败.通常快速失败意味着先前的IO操作(如打开文件)将首先失败.您可以编写一个不忽略IOExceptions的close,但如果try/catch块中的某些内容失败,这可能会破坏异常的真正原因.

你想要的是类似下面的东西(在大多数情况下是矫枉过正的)

try {
    // write to bw.
    bw.close(); // throw IOException if an error occurs.

} finally {
    // don't clobber a previous IOException
    IOUtils.closeQuietly(bw);
}
Run Code Online (Sandbox Code Playgroud)

  • 您使用不正确 - "IOUtils.closeQuietly()"不是一般用途,而是直接在Closable上调用close().它的预期用例是确保在finally块内调用close()以避免资源泄漏 - 所有错误处理(日志记录,异常包装和重新抛出)都应该在此之前完成 - 请参阅Fabian的回答 (2认同)
  • 我已经检查了[源代码](https://commons.apache.org/proper/commons-io/apidocs/src-html/org/apache/commons/io/IOUtils.html)并阅读了文档.`closeQuietly()`只不过是对一个忽略异常的try/catch包围的`close()`的调用.文件同意.您可以**使用`closeQuietly()`代替close(),而`finally {}`块是理想的地方. (2认同)