Derek
Derek

Reputation: 113

Java Detect Closed Stream

I have a general socket implementation consisting of an OutputStream and an InputStream.

After I do some work, I am closing the OutputStream.

When this is done, my InputStream's read() method returns -1 for an infinite amount of time, instead of throwing an exception like I had anticipated.

I am now unsure of the safest route to take, so I have a few of questions:

Thanks!

Upvotes: 11

Views: 8450

Answers (5)

Stephen C
Stephen C

Reputation: 718768

Am I safe to assume that -1 is only returned when the stream is closed?

Yes.

You should not assume things like this. You should read the javadoc and implement according how the API is specified to behave. Especially if you want your code to be robust (or "safe" as you put it.)

Having said that, this is more or less what the javadoc says in this case. (One could quibble that EOF and "stream has been closed" don't necessarily mean the same thing ... and that closing the stream by calling InputStream.close() or Socket.close() locally will have a different effect. However, neither of these are directly relevant to your use-case.)

Is there no way to recreate the IO exception that occurs when the connection is forcefully broken?

No. For a start, no exception is normally thrown in the first place, so there is typically nothing to "recreate". Second the information in the original exception (if there ever was one) is gone.

Should I send a packet that will tell my InputStream that it should close instead of the previous two methods?

No. The best method is to test the result of the read call. You need to test it anyway, since you cannot assume that the read(byte[]) method (or whatever) will have returned the number of bytes you actually asked for.

I suppose that throwing an application specific exception would be OK under some circumstances.

But remember the general principle that exceptions should not be used for normal flow control.


One of the other answers suggests creating a proxy InputStream that throws some exception instead of returning -1.

IMO, that is a bad idea. You end up with a proxy class that claims to be an InputStream, but violates the contract of the read methods. That could lead to trouble if the proxy was passed to something that expected a properly implemented InputStream.

Second, InputStream is an abstract class not an interface, so Java's dynamic proxy mechanism won't work. (For example, the newProxyInstance method requires a list of interfaces, not classes.)

Upvotes: 2

Vladimir Dyuzhev
Vladimir Dyuzhev

Reputation: 18336

Is there no way to recreate the IO exception that occurs when the connection is forcefully broken?

I'll answer this one. InputStream is only an interface. If you really want implementation to throw an exception on EOF, provide your own small wrapper, override read()s and throw an exception on -1 result.

The easiest (least coding) way would be to use a Dynamic Proxy:

InputStream pxy = (InputStream) java.lang.reflect.Proxy.newProxyInstance(
    obj.getClass().getClassLoader(),
    new Class[]{ InputStream.class },
    new ThrowOnEOFProxy(obj));

where ThrowOnEOFProxy would check the method name, call it and if result is -1, throw IOException("EOF").

Upvotes: -1

Edwin Dalorzo
Edwin Dalorzo

Reputation: 78579

Also, closing the Outputs Stream in a socket closes the socket itself.

This is what the JavaDoc for Socket says:

public OutputStream getOutputStream() throws IOException

Returns an output stream for this socket.

If this socket has an associated channel then the resulting output

stream delegates all of its operations to the channel. If the channel is in non-blocking mode then the output stream's write operations will throw an IllegalBlockingModeException.

Closing the returned OutputStream will close the associated socket.

Returns:
    an output stream for writing bytes to this socket. 
Throws:
    IOException - if an I/O error occurs when creating the output stream

or if the socket is not connected.

Not sure that this is what you actually want to do.

Upvotes: 0

z7sg Ѫ
z7sg Ѫ

Reputation: 3203

According to the InputStream javadoc, read() returns:

the next byte of data, or -1 if the end of the stream is reached.

So you are safe to assume that and it's better to use what's specified in the API than try and recreate an exception because exceptions thrown could be implementation-dependent.

Upvotes: 0

WhiteFang34
WhiteFang34

Reputation: 72039

The -1 is the expected behavior at the end of a stream. See InputStream.read():

Reads the next byte of data from the input stream. The value byte is returned as an int in the range 0 to 255. If no byte is available because the end of the stream has been reached, the value -1 is returned. This method blocks until input data is available, the end of the stream is detected, or an exception is thrown.

You should still catch IOException for unexpected events of course.

Upvotes: 8

Related Questions