JavaRanch Home    
 
This page:         last edited 08 February 2008         What's Changed?         Edit

Available Doesnt Do What You Think It Does   

It is not uncommon to see a code snippet like this:


InputStream is = // some input
OutputStream os = // some output
byte buffer = new byte[1024];
while (is.available()>0) {
   is.read(buffer);
   os.write(buffer);
}
attached to a question wondering why the data is not being moved completely. The answer is that available() doesn't do what you think it does. If we look at the documentation for JavaDoc:java.io.InputStream :

public int available() throws IOException

Returns the number of bytes that can be read (or skipped over) from this input 
stream without blocking by the next caller of a method for this input stream. 

It is clear that available() does not return the amount of data left to be read, but the amount of data that can be read without blocking (pausing to wait for more data from the file/socket/database/etc.). In some cases this may return zero while there are still bytes that should be read - the 0 means that there are 0 bytes available right now (with no blocking). This may happen for various reasons - a hard drive may be busy repositioning its magnetic reader, or a network connection may be busy, or perhaps you're waiting for a user somewhere to type something before their information may be sent. Or it may be because the file you're reading really has no additional bytes to read, because you've reached the end. Using available() you have no way of knowing whether or not you should try to read the bytes anyway.

A more correct way to use a stream to copy a file is to check the return value of read for the end-of-file value (-1):


InputStream is = // some input
OutputStream os = // some output
byte buffer = new byte[1024];
int bytesRead;
while ((bytesRead = is.read(buffer)) != -1) {   
   os.write(buffer, 0, bytesRead);
}
When this code completes, you know that all the bytes really have been read and copied, because the while loop doesn't complete until read() returns -1, indicating the end of input.

Readers don't have an available() method, but they do have a ready() method, which is similar (and similarly useless in most cases). This method simply returns false if the reader has no chars available right now, just as available() would return 0. A return value of false does not (necessarily) mean that there are no more characters to read; it just means there will be some delay before you can read them.


JavaIoFaq

JavaRanchContact us — Copyright © 1998-2014 Paul Wheaton