30

java.io.InputStream.close()方法被声明为抛出一个IOException. 在什么情况下实际会抛出这样的异常?

编辑:是的,我已经阅读了 javadoc。任何人都可以比“发生 I/O 错误时”更具体吗?关闭 ? 时会发生什么I/O 错误InputStream

4

4 回答 4

21

在从文件系统读取输入流的情况下,当文件系统本身在关闭期间更新文件上的最后访问时间元数据或其他一些元数据时,可能会引发错误。无论如何,这在实践中几乎从未发生过。

在从网络连接读取输入流的情况下,关闭错误更容易想象。网络套接字的正常关闭实际上涉及通过连接发送关闭请求(TCP/IP FIN 数据包)并等待另一端确认此关闭请求。(事实上​​,连接的另一端会依次发送一个关闭请求,关闭端确认该请求。)因此,对于套接字输入流,关闭操作实际上涉及通过连接发送流量,因此关闭可以失败并出现错误。

请注意,在许多实现中,如果流已经关闭,close()通常不会抛出异常;IOException它只是默默地无法再次关闭流。

于 2013-05-04T00:49:02.400 回答
5

我正在查看 Java 源代码,并发现了一些有趣的东西,这表明了IOException原因。InputStream 是一个抽象类。因此,我们无法预测将关闭的输入类型,因此保持信息流动是件好事。

使用该输入流的任何代码都需要能够抛出IOException,因为关闭输入流可能会失败。如果它失败了,任何使用实现的人都需要知道它,因为很有可能需要处理它。

了解 Java 中异常结构的布局很重要。当然,每个例外都会扩展Exception. 但是,还有更广泛的异常类别:java.lang.IOException是其中之一,并涵盖了所有可能的输入/输出异常。当我们说存在 I/O 错误时,我们指的是任何属于IOException. 因此,许多例外都扩展了这一例外,例如FileNotFoundException,EOFException等,因为拥有一个广泛的、总体的例外来管理这些例外是很重要的。

因此,任何 IO 类都需要能够在关闭时抛出任何各种 IOException。close()因此必须抛出IOException- 这使得它的实现也能够抛出任何扩展IOException。这就是close()throws IOException- 异常被继承的原因,并且您需要在关闭流时能够处理任何 IOExceptions。


这里有几个值得注意的场景:

  • 您不能关闭 IOStream 两次,尽管这样做通常不会引发异常
  • 内容变得不可访问(例如磁盘被卸载)(这close()实际上对操作系统至关重要,因为它需要指示文件何时不再忙)
  • 通用来源已关闭
  • IOException(例如FileNotFoundException)的所有其他子类未涵盖的任何一般故障

您可以检查IOException由运行引起的原因Exception.getMessage()

于 2013-05-04T00:49:49.340 回答
4

最终必须进行底层关闭系统调用,例如在 linux http://linux.die.net/man/2/close上。该调用被记录为失败EIO:“发生 I/O 错误。” 所以原因是,底层文件系统close调用可能会失败。

于 2013-05-04T01:33:38.993 回答
1

我自己也想过这个问题,并且几年前对这个话题做了一些研究。这是我所知道的......

如果您查看您提供的链接中的 javadoc,它清楚地指出“InputStream 的 close 方法什么都不做”,所以它不可能抛出异常,对吗?但是再看看 IOException 的所有子类,你会发现在很多情况下 inputstream 的子类可能无法关闭流。所以我最好的猜测是这个异常是为子类设计的以使用它。

http://docs.oracle.com/javase/6/docs/api/java/io/IOException.html

在某些情况下,这只不过是一种麻烦,而在其他情况下,它清楚地表明出了问题。这完全取决于您使用的输入流实现类型。

于 2013-05-04T00:50:20.033 回答