问题
Does Java have any reliable way of determining whether a java.io.InputStream
is closed before I attempt to read from it?
My use case is that I have a method that takes an InputStream
argument and reads from it. The method runs in its own thread, and I want to terminate the thread if the input stream is closed.
InputStream
implements Closeable
, which provides a close()
method but apparently no way to query if the instance has already been closed.
Attempting to read from closed InputStream
will throw an IOException
, but that could have other causes, and there is nothing in the interface contract stating whether this condition is permanent or if, under some circumstances, there is a chance it will go away sometime.
Callers of my method can supply any subclass of InputStream
they wish, so relying on specific subclass behavior is not an option.
Any other ideas?
回答1:
No. There's no API for determining whether a stream has been closed.
Applications should be (and generally are) designed so it isn't necessary to track the state of a stream explicitly. Streams should be opened and reliably closed in an ARM block, and inside the block, it should be safe to assume that the stream is open. When an an ARM block is used idiomatically, it naturally scopes the reference to a stream so that no one can access it after it's closed.
There are a number of ways that streams can be logically "closed", and many stream implementations will not detect this until a read()
call is made. For example, if a server closes a socket, the internal state of the socket object in your client is unlikely to asynchronously reflect this; instead, the next call to read data will detect the closure and update the state. In this example, if the socket was closed cleanly, the read()
call would return EOF to signal to the application that all data was safely received. If the connection was terminated abnormally, the call would throw an exception to indicate some data may have been lost.
It is reasonable to assume that a stream that has thrown an IOException
is dead, and further attempts to read from it will continue to fail. If you could have detected this condition before making the call to read()
, you'd presumably still handle it in the same way.
The exception to this approach is that some streams support a read timeout, where an exception is raised if no input is received for some time, but the stream remains valid. It would only make sense for a caller to pass such a stream to a method that explicitly supports retrying reads.
回答2:
I think the cleanest way to do this is add a custom class which extends any sort of InputStream that you want to use. Add it to your utils package or something. And have in that class a value called:
private boolean isClosed = false;
So when you call close you can do something like:
@Override
public void close() throws IOException {
if(!isClosed){
super.close();
isClosed = true;
}
}
public boolean isClosed() {
return isClosed;
}
It'd be the cleanest way for your specific requirement in my opinion. Also you can manage the error in a way that you can return a specific custom error on different scenarios.
来源:https://stackoverflow.com/questions/51829782/find-out-whether-an-inputstream-is-closed