在尝试读取java.io.InputStream
之前,Java是否有任何可靠的方法来确定InputStream
是否已关闭?
我的用例是我有一个采用InputStream
参数并从中读取的方法。该方法在其自己的线程中运行,如果输入流关闭,我想终止该线程。
Closeable
实现了close()
,该方法提供了一种InputStream
方法,但是显然无法查询实例是否已关闭。
尝试从封闭的IOException
中读取将引发InputStream
,但这可能有其他原因,并且接口合同中没有任何内容说明这种情况是否永久存在,或者在某些情况下,有可能它会在某个时候消失。
我的方法的调用者可以提供他们希望的php
的任何子类,因此不能依靠特定的子类行为。
还有其他想法吗?
答案 0 :(得分:4)
不。没有用于确定流是否已关闭的API。
应该(通常是)设计应用程序,这样就不必显式跟踪流的状态。流应该在ARM块中打开并可靠地关闭,并且在该块内部,应该安全地假定流是打开的。当惯用ARM块时,它自然会将引用的作用域限定为流,以便在关闭流之后没有人可以访问它。
有多种方法可以在逻辑上“关闭”流,并且在进行read()
调用之前,许多流实现都无法检测到这一点。例如,如果服务器关闭套接字,则客户端中套接字对象的内部状态不太可能异步反映这一情况。相反,下一次读取数据的调用将检测到关闭并更新状态。在此示例中,如果完全关闭了套接字,则read()
调用将返回EOF以向应用程序发出信号,表明已安全接收所有数据。如果连接异常终止,则调用将引发异常,以指示某些数据可能已丢失。
可以合理地假设抛出IOException
的流已死,并且进一步尝试读取该流将继续失败。如果在调用read()
之前 可以检测到这种情况,那么您大概还是可以用相同的方式来处理它。
此方法的例外是某些流支持读取超时,如果一段时间未收到任何输入,则会引发异常,但该流仍然有效。调用方将这样的流传递给显式支持重试读取的方法才有意义。
答案 1 :(得分:0)
我认为最干净的方法是添加一个自定义类,该类可扩展您要使用的任何InputStream。将其添加到您的utils包中。并且在该类中有一个值:
private boolean isClosed = false;
因此,当您致电close时,您可以执行以下操作:
@Override
public void close() throws IOException {
if(!isClosed){
super.close();
isClosed = true;
}
}
public boolean isClosed() {
return isClosed;
}
我认为这将是满足您特定要求的最干净的方法。另外,您还可以通过在不同情况下返回特定的自定义错误的方式来管理错误。