I am using DataInputStream to read some bytes from a socket. I have a expected number of bytes to read from the stream (after decoding a header, I know how many bytes are in the message) It works 99% of the time but occasionally I will have the number of bytes read be less than len.
int numRead = dis.read(buffer, 0, len);
What could cause numRead to be less than len? It's not -1. I would expect the behavior of read to block until the stream is closed or EOF is reached, but if it's a socket underlying the streams this shouldn't happen unless the socket closes, right?
Is there a way of reading bytes from a socket that will always ensure that you read len bytes?
Thanks
A data input stream lets an application read primitive Java data types from an underlying input stream in a machine-independent way. An application uses a data output stream to write data that can later be read by a data input stream. DataInputStream is not necessarily safe for multithreaded access.
A data input stream enables an application to read primitive Java data types from an underlying input stream in a machine-independent way(instead of raw bytes). That is why it is called DataInputStream – because it reads data (numbers) instead of just bytes.
DataInputStream is a kind of InputStream to read data directly as primitive data types. BufferedInputStream is a kind of inputStream that reads data from a stream and uses a buffer to optimize speed access to data. data is basicaly read ahead of time and this reduces disk or network access.
It returns an int because when the stream can no longer be read, it returns -1. If it returned a byte, then -1 could not be returned to indicate a lack of input because -1 is a valid byte.
EDIT: For a general stream, you just keep reading until you've read everything you want to, basically. For an implementation of DataInput
(such as DataInputStream
) you should use readFully
, as suggested by Peter Lawrey. Consider the rest of this answer to be relevant for the general case where you just have an InputStream
.
It's entirely reasonable for an InputStream
of any type to give you less data than you asked for, even if more is on its way. You should always code for this possibility - with the possible exception of ByteArrayInputStream
. (That can still return less data than was requested, of course, if there's less data left than you asked for.)
Here's the sort of loop I'm talking about:
byte[] data = new byte[messageSize];
int totalRead = 0;
while (totalRead < messageSize) {
int bytesRead = stream.read(data, totalRead, messageSize - totalRead);
if (bytesRead < 0) {
// Change behaviour if this isn't an error condition
throw new IOException("Data stream ended prematurely");
}
totalRead += bytesRead;
}
You can use DataInputStream this way.
byte[] bytes = new byte[len];
dis.readFully(bytes);
This will either return with all the data read or throw an IOException.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With