文件关闭时,为什么我会关心IOExceptions?

我经常在Java代码中看到这种事情……

try { fileStream.close(); } catch (IOException ioe) { /* Ignore. We do not care. */ } 

这是合理的还是骑士的?

我什么时候关心关闭文件失败? 忽略此exception有什么含义?

至少会记录exception。

我已经看到它偶尔发生,如果由于无法刷新数据而关闭文件的尝试失败。 如果您只是吞下exception,那么您在没有意识到的情况下丢失了数据。

理想情况下,如果您已经处于另一个exception的上下文中(例如,您处于finally块中,但由于另一个exception,而不是已完成try块),您应该吞下exception,但如果您的操作是否则抛出它成功的。 不幸的是,整理出来有点难看:(

但是,你应该至少登录它。

您会关心close()方法是否将写入的内容从缓冲区刷新到文件系统,并且失败了。 例如,如果您要写入的文件位于已不可用的远程文件系统上。

注意以上重新。 刷新适用于任何输出流,而不仅仅是文件。

最常见的close()问题是磁盘空间不足,或者正如Brian所提到的那样,一个远程流已经消失了。

注意:

你应该真的看到类似的东西(注意:我没有编译检查过这个)

 SomeKindOfStream stream = null; Throwable pending = null; try { stream = ...; // do stuff with stream } catch (ThreadDeath t) { // always re-throw thread death immediately throw t; } catch (Throwable t) { // keep track of any exception - we don't want an exception on // close() to hide the exceptions we care about! pending = t; } finally { if (stream != null) try { stream.close(); } catch (IOException e) { if (pending == null) pending = e; } } if (pending != null) { // possibly log - might log in a caller throw new SomeWrapperException(pending); // where SomeWrapperException is unchecked or declared thrown } } 

为什么这一切?

请记住,Java一次只能跟踪一个“挂起”exception。 如果主try块的主体抛出exception, 并且 finally中的close()抛出exception,那么你唯一知道的就是close()。

以上结构执行以下操作:

  • 跟踪尝试中抛出的任何抛掷物
  • 如果exception是线程死亡,请立即重新抛出!
  • 关闭时,如果我们没有挂起的exception,则跟踪关闭exception; 否则应该跟踪以前抛出的exception。 (在这种情况下,您应该尝试记录close()错误)
  • 最后,如果有待处理的exception,请处理它。 我通常把它包起来并重新抛出它。 就个人而言,我使用一个未经检查的包装器,因此我不需要在调用链中声明抛出所有调用者。

为了做到这一点,我通常使用模板方法模式来创建exception管理,然后覆盖作为try主体的doWork()方法。