简体   繁体   English

为什么声明InputStream.close()会抛出IOException?

[英]Why is InputStream.close() declared to throw IOException?

The java.io.InputStream.close() method is declared to throw an IOException . 声明java.io.InputStream.close()方法抛出IOException Under what circumstances would such an exception actually be thrown? 在什么情况下会抛出这样的例外?

Edit: Yes I have read the javadoc. 编辑:是的我已经阅读了javadoc。 Can anybody be more specific than "when an I/O error occurs"? 任何人都可以比“发生I / O错误时”更具体吗? What I/O error can occur while closing an InputStream ? 关闭InputStream可能发生什么 I / O错误?

In the case of input stream reading from a file system, an error can be raised while the file system itself updates the last access time metadata, or some other metadata, on a file during closure. 在从文件系统读取输入流的情况下,当文件系统本身在关闭期间更新文件上的最后访问时间元数据或一些其他元数据时,可以引发错误。 Anyway, this happens almost never in practice. 无论如何,这几乎从未在实践中发生过。

In the case of an input stream reading from a network connection, an error on closure is a bit more conceivable. 在从网络连接读取输入流的情况下,可以更容易地想到关闭时的错误。 A normal closure of a network socket actually involves a closure request (TCP/IP FIN packet) being sent over the connection and waiting for the other end to acknowledge this closure request. 网络套接字的正常关闭实际上涉及通过连接发送的关闭请求(TCP / IP FIN数据包),并等待另一端确认此关闭请求。 (In fact, the other end of the connection then in turn sends a closure request, which the closing end acknowledges.) So in the case of a socket input stream, a closure operation actually involves sending traffic over the connection and the closure can thus fail with an error. (实际上,连接的另一端然后又发送一个闭包请求,结束端确认。)因此,在套接字输入流的情况下,闭包操作实际上涉及通过连接发送流量,因此闭包可以失败并出错。

Note that in many implementations, close() generally doesn't throw an IOException if the stream is already closed; 请注意,在许多实现中,如果流已经关闭, close()通常不会抛出IOException ; it simply fails silently to close the stream again. 它只是无声无法再次关闭流。

I'm looking through the Java source code, and have found something interesting which is indicative of the IOException reason. 我正在查看Java源代码,并找到了一些有趣的东西,它表明了IOException原因。 InputStream is an abstract class . InputStream 是一个抽象类 We therefore can't predict the kind of input which will be closed, so it's good to keep information flowing. 因此,我们无法预测将要关闭的输入类型,因此保持信息流动是有益的。

Whatever code uses that input stream needs to be able to throw an IOException , because there is a chance that closing the input stream may fail. 无论代码使用什么输入流都需要能够抛出IOException ,因为关闭输入流可能会失败。 If it fails, whatever's using the implementation needs to know about it, because there's a good chance it needs to be handled. 如果它失败了,那么使用实现的任何东西都需要了解它,因为它很有可能需要处理。

It's important to understand the layout of the Exception structure in Java. 理解Java中Exception结构的布局非常重要。 Every exception, of course, extends Exception . 当然,每个例外都会扩展Exception However, there are also broader categories of exceptions: java.lang.IOException is one of these, and covers all possible input/output exceptions. 但是,还有更广泛的异常类别: java.lang.IOException是其中之一,并涵盖所有可能的输入/输出异常。 When we say there has been an I/O error, we're referencing anything which falls under IOException . 当我们说有一个I / O错误时,我们引用任何属于IOException东西。 As a result, many exceptions extends this one, eg FileNotFoundException , EOFException , etc. as it's important to have a broad, overarching exception to manage these. 因此,许多异常扩展了这一个,例如FileNotFoundExceptionEOFException等,因为管理这些异常具有广泛的,总体的例外非常重要。

As a result, any IO class will need to be able to throw any of the various IOExceptions on close. 因此,任何IO类都需要能够在关闭时抛出任何各种IOExceptions。 close() therefore must throw IOException - this gives its implementation the ability to throw any of the extensions of IOException as well. 因此close()必须抛出IOException - 这使得它的实现能够抛出IOException任何扩展。 This is why close() throws IOException - exceptions are inherited, and you need to be able to any of the IOExceptions when closing a stream. 这就是为什么close()抛出IOException - 继承异常,并且在关闭流时需要能够使用任何IOExceptions。


Here are a couple scenarios worth noting: 以下是一些值得注意的情景:

  • You can't close an IOStream twice, though this generally doesn't throw an exception if you do 您不能两次关闭IOStream,但如果这样做,通常不会抛出异常
  • The content becomes inaccessible (eg a disk was unmounted) (The close() is actually critical for the operating system, as it needs to have an indicator of when the file is no longer busy) 内容变得无法访问(例如,磁盘已卸载)( close()实际上对操作系统至关重要,因为它需要指示文件何时不再忙)
  • The generic source has closed 通用源已关闭
  • Any generic failure not covered by all other subclasses of IOException (eg FileNotFoundException ) IOException的所有其他子类未涵盖的任何泛型故障(例如FileNotFoundException

You can check what caused an IOException by running Exception.getMessage() . 您可以通过运行Exception.getMessage()来检查导致IOException的原因。

The underlying close system call will have to be made eventually, eg on linux http://linux.die.net/man/2/close . 必须最终进行底层关闭系统调用,例如在linux http://linux.die.net/man/2/close上 That call is documented to fail with EIO : "An I/O error occurred." 记录该调用与EIO失败:“发生I / O错误。” So the reason is, that the underlying file system close call can fail. 原因是,底层文件系统close调用可能会失败。

I have wondered about this myself and have done a little research on this topic few years ago. 我自己也很想知道这件事,几年前就这个话题做了一些研究。 This is what I know.... 这就是我所知道的......

If you look at the javadoc in the link you provided, it clearly states that "The close method of InputStream does nothing", so there is no way it would throw an exception, correct? 如果你查看你提供的链接中的javadoc,它会清楚地说明“InputStream的close方法什么都不做”,所以它不会抛出异常,对吗? But then looking at all of the subclasses of IOException you will see that there are many situations where subclasses of inputstream may not be able to close the stream. 但是,然后查看IOException的所有子类,您将看到有许多情况,其中inputstream的子类可能无法关闭流。 So my best guess is that this exception is designed for subclasses to make use of it. 所以我最好的猜测是这个异常是为子类设计的,以便利用它。

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

In some cases, it is nothing more than a nuisance, and in others it clearly indicates that something went wrong. 在某些情况下,它只不过是一种麻烦,而在其他情况下,它清楚地表明出现了问题。 It all depends on what type of inputstream implementation you are making use of. 这完全取决于您正在使用的输入流实现类型。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM