Only 44 hours left in the trailboss' kickstarter!

New rewards and stretch goals. CLICK HERE!



  • Post Reply Bookmark Topic Watch Topic
  • New Topic

InputStream.read(byte[])  RSS feed

 
Layne Lund
Ranch Hand
Posts: 3061
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
According to the API docs, I see that InputStream.read(byte[]) returns the number of bytes that are actually read. I have a question about this that does not seem to be clearly stated in the docs. Let's say I have the following code:

If the code marked "here" in the if statement is reached, does it mean that the InputStream reached EOF before it could fill the buffer? Or in other words, is there any reason other than EOF that would cause the read() method to return without reading enough bytes to fill the array named buff?

Thanks,

Layne
 
Michael Ernest
High Plains Drifter
Sheriff
Posts: 7292
Netbeans IDE VI Editor
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Other than a signal or an exception/error, both of which would not allow read to return properly, no.
 
Norm Radder
Rancher
Posts: 1733
22
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Would it be possible when reading from the net to get some of the bytes without being at EOF? Or would the read() block?
 
Layne Lund
Ranch Hand
Posts: 3061
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Originally posted by Michael Ernest:
Other than a signal or an exception/error, both of which would not allow read to return properly, no.


If an exception is thrown, then execution won't reach the line marked "here", right? Either execution moves to a catch clause in the same method or the call stack is unwound until a catch is found.

Layne
 
Layne Lund
Ranch Hand
Posts: 3061
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Originally posted by Norm Radder:
Would it be possible when reading from the net to get some of the bytes without being at EOF? Or would the read() block?


That's the idea that I was thinking of, but not specifically for network I/O. In fact, the question can be generalized for any type of InputStream: does read() block until either enough bytes are available to read or EOF is reached?

Layne
 
Stan James
(instanceof Sidekick)
Ranch Hand
Posts: 8791
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Try a quick experiment - a server that writes one character a second and a client that reads a buffer of 10. See what available() tells you, too. Oh, and let us know!
 
Layne Lund
Ranch Hand
Posts: 3061
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Originally posted by Stan James:
Try a quick experiment - a server that writes one character a second and a client that reads a buffer of 10. See what available() tells you, too. Oh, and let us know!


As I said, I'm not working with network I/O at the moment, but it would be an interesting experiment if I can get around to it. I'm dealing with files instead and because I need to move around in the file, I decided to use RandomAccessFile instead of FileInputStream. So my question is also for RandomAccessFile.read(). From what I can tell, RandomAccessFile.read() < buff.length if and only if EOF is reached, but it would be nice to confirm this from the specs. I should probably download the JLS and see what it has to say, if anything...

Layne
 
Joe Ess
Bartender
Posts: 9406
12
Linux Mac OS X Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
The javadoc for RandomAccessFile.read(byte[]) says:

public int read(byte[] b) throws IOException
Reads up to b.length bytes of data from this file into an array of bytes. This method blocks until at least one byte of input is available.

I think it's pretty clear that it is the same as InputStream.read(byte[]), which can return anywhere between 1 and byte[].length bytes. That's the reason it returns an integer indicating the number of bytes read.
If you want to read a full byte array from a file, use RandomAccessFile.readFully():

public final void readFully(byte[] b) throws IOException
Reads b.length bytes from this file into the byte array, starting at the current file pointer. This method reads repeatedly from the file until the requested number of bytes are read. This method blocks until the requested number of bytes are read, the end of the stream is detected, or an exception is thrown.
 
Layne Lund
Ranch Hand
Posts: 3061
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I need the last few bytes even if my buffer is longer than the number of bytes available. I just want to know what it means if the return value is not the same as the length of the buffer. Is it guaranteed that the next call to read() will return -1 (i.e. EOF was encountered).

Of course, it looks like readFully() might help solve my problem. However, I don't like the idea of using exceptions to control program flow. Once an exception is thrown, I still need to read the last few bytes and process them. Hmm...well, this gives me something to think about.

Layne
 
Jim Yingst
Wanderer
Sheriff
Posts: 18671
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
The fact that RandomAccessFile has a read() and a readFully() does indeed point up the difference between the two. The read() method does not guarantee that the read will be "complete" (i.e. it may be less than the buffer size even without reaching EOF). The authors of the API very deliberately avoided making any guarantees in this area. For a socket stream or a piped input stream, it's possible that the remaining data simply has not been sent yet, and the API is written to allow the method to return ASAP rather than wait indefinitely for more data. For a file stream, incomplete reads are less common, but they do still occur sometimes, and don't require some sort of exception. (Contrary to Michael Ernest's post above.) Possible reasons are (a) the file is fragmented and it will take a few extra milliseconds for the disc reader to get to the next fragment, or (b) there's a hardware buffer somewhere which is smaller than the size of the byte[] array you're requesting. In this case, the system may simply pass on whatever bytes are immediately available, as long as there's at least one.

Note that the available() method has very similar issues. It does not tell you how many bytes may eventually be available from a given stream - it just tells you how many can be grabbed right now. Which is seldom very useful. I think it was intended to try to facilitate high-volume multi-threaded services (check to see if any bytes are available before you block the thread to get them) but this need is now much better met by some of the NIO classes that came out in 1.4. FileChannel's read(), transferTo() and transferFrom() also have similar issues, at least as far as the API is concerned. But in practice the implementations I've tested seem to avoid any incomplete reads. Nonetheless if you want to write reliable cross-platform code, I would recommend that for any method that returns the number of bytes which it retrieves, you should check that return value and react accordingly if the read is incomplete. Generally this implies some sort of loop to keep going until you get what you need.
 
Layne Lund
Ranch Hand
Posts: 3061
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Jim,

Thanks for taking the time to reply to this old thread. I appreciate your input. Unfortunately, I haven't had much time to work on this project lately. I need to get back into it soon, so I appreciate the reminder even if it wasn't intended as such.

I will look more closely at the differences between read() and readFully(). From the descriptions given here, it looks like readFully() will serve my purposes. If not, I will use your suggestion of a loop.

Layne
 
  • Post Reply Bookmark Topic Watch Topic
  • New Topic
Boost this thread!