According to the java api, the InputStream.read()
is described as:
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.
I have a while(true)
loop doing a read and I always get -1 when nothing's sent over the stream. That's expected.
My question is when would read() ever block? Since if it doesn't get any data it returns -1. I would expect a blocking read to wait until data is received. If you've reached the end of the input stream, shouldn't read() simply wait for data instead of returning -1?
Or does read() only block if there's another thread accessing the stream and your read() cannot access the stream?
Which leads me to my next question. I used to have event listener (provided by my library) that would notify me when data is available. When I was notified I would call while((aByte = read()) > -1)
store the byte. I was puzzled when I'd get TWO events in very close time proximity and not all my data was being displayed. It seemed like only the tail end of the second event's data would be displayed and the the rest was missing.
I eventually changed my code so that when I get an event I'd called if(inputStream.available() > 0) while((aByte = read()) > -1)
store the byte. Now it worked properly and all my data was displayed.
Can someone explain this behavior? The InputStream.available()
is said to return the number of bytes you can read before blocking the next caller (of the stream?). Even if I don't use .available() I would expect the read of the first event to just block the read of the second event, but not erase or consume too much stream data. Why would doing this cause not all of my data to be displayed?
It returns -1 if it's end of stream. If stream is still open (i.e. socket connection) but no data has reached the reading side (server is slow, networks is slow,...) the read() blocks.
You don't need call available(). I have a hard time understanding your notification design, but you don't need any calls except read() itself. Method available() is there for convenience only.
InputStream
is just an abstract class, unfortunately the implementation decides what happens.What happens if nothing is found:
Sockets (i.e.
SocketInputStream
) will block until data is received (by default). But it's possible to set a timeout (see:setSoTimeout
), then theread
will block for x ms. If still nothing is received then aSocketTimeoutException
will be thrown.But with or without timeout, reading from a
SocketInputStream
can sometimes result in a-1
. (E.g. when multiple clients simultaneously connect to the samehost:port
, then even though the devices seem connected, the result of aread
could immediately restult in a-1
(never returning data).)Serialio communication will always return
-1
; You can also set a timeout (usesetTimeoutRx
), theread
will first block for x ms, but the result will still be-1
if nothing's found. (Remark: but there are multiple serial io classes available, behaviour could be vendor dependent.)Files (readers or streams) will result in an
EOFException
.Work to a Generic Solution:
DataInputStream
, then you can use methods likereadByte
,readChar
, etc . All-1
values are converted toEOFException
. (PS: If you perform a lot of small reads, then it's a good idea to wrap it in aBufferedInputStream
first)SocketTimeoutException
andEOFException
extendIOException
, and there are several other possibleIOException
's. It is convenient to just check forIOException
's to detect communication issues.Another sensitive topic is flushing.
flush
in terms of sockets means "send it now", but in terms of Serialio it means "discard the buffer".The underlying data source for some implementations of
InputStream
can signal that the end of the stream has been reached, and no more data will be sent. Until this signal is received, read operations on such a stream can block.For example, an
InputStream
from aSocket
socket will block, rather than returning EOF, until a TCP packet with the FIN flag set is received. When EOF is received from such a stream, you can be assured that all data sent on that socket has been reliably received, and you won't be able to read any more data. (If a blocking read results in an exception, on the other hand, some data may have been lost.)Other streams, like those from a raw file or serial port, may lack a similar format or protocol to indicate that no more data will be available. Such streams can immediately return EOF (-1) rather than blocking when no data are currently available. In the absence of such a format or protocol, however, you can't be sure when the other side is done sending data.
With regard to your second question, it sounds like you may have had a race condition. Without seeing the code in question, I'm guessing that the problem actually lay in your method of "display". Perhaps the attempt to display by the second notification was somehow clobbering the work done during the first notification.
I am using eclipse Jetty 9.2.2. I am surprised to see that 10-12% of my request are taking around 500+ mili-seconds each while others get processed within 2-3 mili-seconds each. portion of the code taking
By default the behavior of the provided RXTX InputStream is not compliant.
You have to set the receive threshold to 1 and disable the receive timeout:
Source: RXTX serial connection - issue with blocking read()
I think You can receive the entire data stream if you use thread.sleep()