HOLIDAY SALE! Save 50% on Membership with code HOLIDAY50. Save 15% on Mentorship with code HOLIDAY15.

3) Input / Output (I/O) Lesson

Java Buffered Input Streams

6 min to complete · By Ryan Desmond

Buffering is the process of adding a block of storage between the reader (often a program) and a data source, which will store parts of the data that the reader is requesting. This allows your program to read more than one byte at a time.

Why Use a BufferedInputStream?

When using a buffer, you increase the speed and efficiency since reading and writing to a disk or network are expensive operations. So, by having a middleman that stores sections of the incoming data, you arrive at some key benefits:

  1. Reducing I/O operations
  2. Fluid and smooth data transfer
  3. Reducing delays caused by the data source

How to Use a BufferedInputStream

A buffered Byte stream allows us to read a block of bytes or a collection of bytes at once. Meanwhile, with a traditional Byte stream, you can only read (or write) one byte at a time.

Buffers (for both Byte streams and Character streams) are very common and can be considered "wrapper classes". They "wrap" an existing class (such as FileInputStream), which allows it to add functionality. 

A BufferedInputStream (or BufferedOutputStream) takes an InputStream (or OutputStream) as its constructor parameter. The buffered streams basically add functionality to the base Byte streams. The buffered streams cannot exist without the Byte streams to feed them the bytes.

BufferedInputStream bufferedInputStream = new BufferedInputStream(new FileInputStream("/path/to/file"));

That line above has quite a bit going on. You are creating the new FileInputStream on the fly within the parameter list of the BufferedInputStream. You can do this because you don't actually need an object of type FileInputStream. So you can just create it using the new keyword and immediately pass it to the BufferedInputStream. Normally, you'll break that initialization up into several lines, as you can see below.

Here's an example of creating and using BufferedInputStream to read a file and print the contents to a file:

public class BufferedInputStreamExample {
  public static void main(String[] args) {
    // you need to declare these streams outside 
    // the try block since you need to 
    // access them and close in the finally block at the bottom
    FileInputStream inputStream = null;
    BufferedInputStream bufferedInputStream = null;

    try {
      inputStream = 
        new FileInputStream("/Users/CodingNomads/Desktop/input_output/file.txt");
      bufferedInputStream = new BufferedInputStream(inputStream);

      // this will hold the collection of bytes that you read at once
      byte[] buffer = new byte[5];
      int bytesRead = 0;
      // this while loop will read the file 5 bytes at a time
      while ((bytesRead = bufferedInputStream.read(buffer)) != -1){
        // print out bytes read to console
        System.out.print(new String(buffer, 0, bytesRead));
      }
    } catch (IOException exc) {
      exc.printStackTrace();
    } finally {
      // there's a possibility that closing these 
      // streams can throw an exception
      // you be using the Try-With-Resources 
      // shortly to avoid the need for this
      try {
        inputStream.close();
        bufferedInputStream.close();
      } catch (IOException ex) {
        ex.printStackTrace();
      }
    }
  }
}

Summary: Java Buffered Input Streams?

  • Buffering creates a block of storage between the reader and the data source
  • Buffering stores parts of the data that is being requested
  • Buffering increases the speed and efficiency of data transfer
  • Buffering in Java can be done by wrapping a class in a buffering class
  • Wrapping is the process of adding a class around another to add functionality
  • The BufferedInputStream class is an example of buffering a Byte stream

Benefits of Buffering

  1. Reducing I/O operations
  2. Fluid and smooth data transfer
  3. Reducing delays caused by the data source