BufferedInputStream/BufferedOutputStream, BufferedReader/BufferedWriter

BufferedInputStream
Constructors/Methods Description
BufferedInputStream(InputStream in),
BufferedInputStream(InputStream in, int size)
Creates a BufferedInputStream with the specified buffer size, and saves its argument, the input stream in, for later use. An internal buffer array of length size is created and stored in buf.
int available(), void close() , int read(), int read(byte[] b, int off, int len), long skip(long n) Meanings of the methods are clear.


BufferedOutputStream
Constructors/Methods Description
BufferedOutputStream(OutputStream out), BufferedOutputStream(OutputStream out, int size). Creates a new buffered output stream to write data to the specified underlying output stream with the specified buffer size. The default is 512.
void write(int b), void write(byte[] b, int off, int len)
void flush() Flushes this buffered output stream. This forces any buffered output bytes to be written out to the underlying output stream.

Advantage of Using Buffered Stream

Reading and writing to a file, getting data one byte at a time, is slow and painstaking. One way to speed up the process is to put a wrapper around the file and put a buffer on it.

Our BufferedInputStream is going to put a buffer onto an InputStream that is specified in the constructor. The actual data source is what you pass it as an InputStream. The BufferedInputStream reads large chunks of data from the InputStream. Then you read individual bytes or small chunks of bytes from the BufferedInputStream. The default buffer size is 512 bytes, but there's a constructor that allows you to specify the buffer size if you want something different.

To improve your efficiency, you read from the object of BufferedInputStream instead of reading directly from the underlying InputStream. And you won't have to go back to the operating system to read individual bytes.

Here is an example :
FilePerformance.java
The pictures is here . On my computer:
copy1 takes 24660 ms.
copy2 takes 930 ms.
copy3 takes 550 ms.
copy4 takes 110 ms.
Remark : if you set length to 1024 in all the methods. The result are more or less the same.

import java.io.*;

public class FilePerformance {
    public static void copy1(File from, File to) throws IOException {
        FileInputStream in = new FileInputStream(from);
        FileOutputStream out = new FileOutputStream(to);
        int ch;
        while((ch = in.read())!= -1) {
            out.write(ch);
        }
        in.close();
        out.close();
    }
    
    public static void copy2(File from, File to) throws IOException {
        FileInputStream in = new FileInputStream(from);
        FileOutputStream out = new FileOutputStream(to);
        int length = 32; // 32 is a power of 2. 
                         // use a power of 2 can increase the performance
        byte[] ch = new byte[length];
        while((length = in.read(ch))!= -1) {
            out.write(ch,0,length);
        }
        in.close();
        out.close();
    }
    
    public static void copy3(File from, File to) throws IOException {
        int bufSize = 1024; // a power of 2, better performance
        BufferedInputStream in  = new BufferedInputStream(
                                      new FileInputStream(from),bufSize);
        FileOutputStream out = new FileOutputStream(to);
        int length = 32; 
        byte[] ch = new byte[length];
        while((length = in.read(ch))!= -1) {
            out.write(ch,0,length);
        }
        in.close();
        out.close();
    }                 
    
    public static void copy4(File from, File to) throws IOException {
        int bufSize = 1024;
        BufferedInputStream in  = new BufferedInputStream(
                                      new FileInputStream(from),bufSize);
        BufferedOutputStream out = new BufferedOutputStream(
                                      new FileOutputStream(to), bufSize);
        int length = 32; 
        byte[] ch = new byte[length];
        while((length = in.read(ch))!= -1) {
            out.write(ch,0,length);
        }
        out.flush();
        in.close();
        out.close();
    }   
    
    public static void main(String[] args) throws IOException {
        File from = new File("pic.jpg");
        File to = new File("pic2.jpg");
        long start = System.currentTimeMillis();
        for(int i = 0; i < 10; i++) {
            System.out.print(i);
            copy1(from, to);
        }
        long end = System.currentTimeMillis();
        System.out.println("\nTime : " + (end - start) + "ms." );
        
        start = System.currentTimeMillis();
        for(int i = 0; i < 10; i++) {
            System.out.print(i);
            copy2(from, to);
        }
        end = System.currentTimeMillis();
        System.out.println("\nTime : " + (end - start) + "ms." );
        
        start = System.currentTimeMillis();
        for(int i = 0; i < 10; i++) {
            System.out.print(i);
            copy3(from, to);
        }
        end = System.currentTimeMillis();
        System.out.println("\nTime : " + (end - start) + "ms." );
        
        start = System.currentTimeMillis();
        for(int i = 0; i < 10; i++) {
            System.out.print(i);
            copy4(from, to);
        }
        end = System.currentTimeMillis();
        System.out.println("\nTime : " + (end - start) + "ms." );
        
    }
}

BufferedReader/BufferedWriter
The classes have similar methods as in BufferedInputStream, BufferedOutputStream.
BufferedReader has one extra method String readLine(). The method reads a line of text. A line is considered to be terminated by any one of a line feed ('\n'), a carriage return ('\r'), or a carriage return followed immediately by a linefeed.