How to use BufferedInputStream read (byte[] b)

BufferedInputStream inherit this method from java.io.InputStream.

It read bytes from the stream that passed in constructor. The number of bytes it read each time is undetermined. It depend on the low level hardware and the status of the network. It also may affected by other factors like the buffer size specified in constructor.

The return value and behavior of read

There is only one reason to cause it return 0. The parameter bytes array b has length of zero. I don't know when this can be meaningful or useful.

If it return -1, means it reach the end of the stream. This should be the loop termination condition.

Both the two situations don't read any bytes. Beside that, this function either read some bytes and return a number that indicate the number of bytes it read.

This is all you can read from the documentation. But there is one more situation you may need to care. The read can block. Without proper intervention, it can hang forever.

Please notice that hang is different from slow, if size of the data in the stream is big, like several hundreds of Mega bytes or your connection speed is low, it could take long to finish. But in the whole process, the read keeps reading bytes.

The hang is the function don't read any bytes and don't return, it stopped working. It's a serious problem no matter in single thread or multi thread environment. Sometimes, kill the JVM is the only solution.

Think about it. There are similar loops in both the client side and the server side. Both receiving data and sending data in a loop. Data comes in small chunks. Not only it's possible the remote loop can stuck, but also the network can delay the arrive of the data.

When the client knows there are rest of the data are traveling the network or wait to be sent, but not actually appears in this side. It will just wait. For how long? No one knows. So you should use this method with caution.

Java code example

 
package com.makble.testjava;
 
import java.io.BufferedInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.net.URLConnection;
 
public class TestRead {
    public static void main (String [] args) {
        String filename = "foo.png";
        String url = "http://makble.com/images/solr-logo.png";
 
        SaveFile(verifyUrl(url), filename, 0);
    }
 
        public static boolean SaveFile(URL url, String filename, int tries) {
        try {
            byte b[] = new byte[100*1024]; 
            //byte b[] = new byte[1024]; 
 
            BufferedInputStream reader = new BufferedInputStream(  getInsWithUserAgent(url), 100*1024 );
 
            FileOutputStream fos = new FileOutputStream(filename);
 
            int readed;
 
            System.out.println("staring read: " + url.toString());
 
            long startTime = System.nanoTime();
            long loopProfiling = System.nanoTime();
 
            while ( (readed = reader.read(b)) != -1)
            {
                Double interval = ((double)(System.nanoTime() - loopProfiling) / 1000000.0);
                loopProfiling = System.nanoTime();
                System.out.println("avaiable:" + reader.available() + " readed:" + readed + " interval: " + interval);
                fos.write(b,0,readed);
            }
            System.out.println("read end: " + url.toString());
            reader.close();
            reader = null;
            b = null;
            fos.close();
        } catch( Exception e ) {
            e.printStackTrace();
 
            System.out.println("try again " + url.toString());
            if( tries > 3 ) return false; 
            return SaveFile(url,filename, tries + 1);
 
        }
        return true;
    }
 
    public static InputStream getInsWithUserAgent(URL url) {
 
        try {
            URLConnection con = url.openConnection();
            con.setDoOutput(true);
            con.setRequestProperty("User-Agent", "Mozilla/5.0 (X11; U; Linux i686; rv:1.9.1.2) Gecko/20090803 Fedora/3.5");
            con.connect();
            return con.getInputStream();
        } catch (IOException e) {
            e.printStackTrace();
            return null;
        }
 
    }
 
    public static URL verifyUrl( String url ){
        if ( !url.toLowerCase().startsWith("http://") && !url.toLowerCase().startsWith("https://"))
            return null;
 
        URL verifiedUrl = null;
        try {
            verifiedUrl = new URL(url);
        } catch ( Exception e ) {
            e.printStackTrace();
            return null;
        }
        return verifiedUrl;
    }
}
 
 

This is a sample output

 
avaiable:0 readed:16074 interval: 0.087911
avaiable:0 readed:16384 interval: 1374.769402
avaiable:0 readed:16384 interval: 2616.544826
avaiable:0 readed:16384 interval: 1647.228844
avaiable:0 readed:16384 interval: 1690.238234
avaiable:0 readed:16384 interval: 2417.012137
avaiable:0 readed:16384 interval: 2574.315924
avaiable:0 readed:16384 interval: 3708.65043
avaiable:0 readed:16384 interval: 1650.908159
avaiable:0 readed:16384 interval: 2504.361629
avaiable:0 readed:16384 interval: 1964.060072
avaiable:0 readed:16384 interval: 1201.708595
avaiable:0 readed:16384 interval: 1730.318898
avaiable:0 readed:16384 interval: 1200.557721
avaiable:0 readed:16384 interval: 989.780473
avaiable:0 readed:16384 interval: 1318.492163
avaiable:0 readed:16384 interval: 3365.612837
avaiable:0 readed:16384 interval: 2503.953312
avaiable:0 readed:16384 interval: 1365.102775
avaiable:0 readed:16384 interval: 4619.680611
avaiable:0 readed:16384 interval: 2837.444766
avaiable:0 readed:16384 interval: 992.421815
avaiable:0 readed:16384 interval: 2224.01609
avaiable:0 readed:16384 interval: 2824.958744
avaiable:0 readed:16384 interval: 1034.572624
avaiable:0 readed:16384 interval: 1264.105232
avaiable:0 readed:2523 interval: 1.990713