Java BufferedInputStream Class


The BufferedInputStream class in Java is part of the java.io package and provides a way to read bytes from an input stream efficiently. This class is a decorator for other input streams and adds functionality for buffering the data, which helps improve performance by reducing the number of read operations from the underlying source.

When dealing with I/O operations, especially when reading from slower sources like files or network connections, buffering can significantly improve the performance of data reading. BufferedInputStream allows for more efficient reading by grouping smaller data chunks into larger buffers, reducing the number of read requests made to the underlying stream.


What is the BufferedInputStream Class?

The BufferedInputStream class is a subclass of InputStream. It reads data from an underlying stream and stores it in an internal buffer. When you call the read() method, it fetches data from the buffer instead of reading directly from the underlying stream. This reduces the number of I/O operations, leading to better performance when reading large amounts of data.

The main advantage of using BufferedInputStream is that it reduces the overhead of I/O operations. Without buffering, every time you call read(), a new request is made to the source stream (e.g., a file or a network socket). With buffering, data is read in larger chunks, and subsequent read operations are faster.


Key Methods of the BufferedInputStream Class

The BufferedInputStream class provides several useful methods, some of which are inherited from InputStream, and others specific to the buffered stream functionality.

  1. int read():
    Reads a single byte of data from the buffered input stream. It fetches data from the buffer if available. If the buffer is empty, it will read more data from the underlying stream.

    int byteData = bufferedInputStream.read();
    
  2. int read(byte[] b):
    Reads a chunk of data into the byte array b. This method attempts to read the data from the buffer first. If the buffer is exhausted, it will read from the underlying stream.
    bufferedInputStream.read(byteArray);
    
  3. void close():
    Closes the buffered stream and releases any system resources associated with it.

  4. int available():
    Returns the number of bytes that can be read from the buffered stream without blocking.

  5. long skip(long n):
    Skips n bytes of data in the buffered stream. If enough data is buffered, it will simply skip over the bytes in the buffer.

  6. void mark(int readlimit):
    Marks a position in the input stream. This can be useful if you want to mark a position and then later call reset() to return to that position.

  7. void reset():
    Resets the stream to the last marked position. If no position has been marked, this throws an IOException.

  8. boolean markSupported():
    Returns true if the stream supports the mark() and reset() methods.


Using the Java BufferedInputStream Class: Practical Examples

Example 1: Reading Data from a File Using BufferedInputStream

One of the most common use cases for BufferedInputStream is reading data from a file. Here's how you can use it to read bytes efficiently from a file.

import java.io.*;

public class BufferedInputStreamExample {
    public static void main(String[] args) {
        try (BufferedInputStream bis = new BufferedInputStream(new FileInputStream("example.txt"))) {
            int byteData;
            while ((byteData = bis.read()) != -1) {
                System.out.print((char) byteData);  // Convert byte to char and print
            }
        } catch (IOException e) {
            System.out.println("An error occurred during reading.");
            e.printStackTrace();
        }
    }
}

Explanation:

  • A BufferedInputStream is created around a FileInputStream, allowing efficient reading of the file example.txt.
  • The read() method is used to read each byte of data from the buffered stream.
  • The byte data is converted to a character and printed to the console.

Output:

This is the content of the file example.txt.

Example 2: Reading a Chunk of Data into a Byte Array

In this example, we will read a chunk of data into a byte array using BufferedInputStream.

import java.io.*;

public class BufferedInputStreamChunkExample {
    public static void main(String[] args) {
        byte[] buffer = new byte[1024];  // Buffer to hold data
        try (BufferedInputStream bis = new BufferedInputStream(new FileInputStream("example.txt"))) {
            int bytesRead;
            while ((bytesRead = bis.read(buffer)) != -1) {
                System.out.println("Read " + bytesRead + " bytes.");
                // Optionally process the bytes here
            }
        } catch (IOException e) {
            System.out.println("An error occurred during reading.");
            e.printStackTrace();
        }
    }
}

 

Explanation:

  • The BufferedInputStream reads data into a byte array buffer in chunks.
  • The read(byte[] b) method reads up to the size of the buffer and returns the number of bytes read.
  • This is a more efficient way to read large files than reading one byte at a time.

Output:

Read 1024 bytes.
Read 1024 bytes.

Example 3: Skipping Data Using BufferedInputStream

The skip() method allows you to skip over a certain number of bytes in the stream. Here's an example where we skip the first 10 bytes of a file.

import java.io.*;

public class BufferedInputStreamSkipExample {
    public static void main(String[] args) {
        try (BufferedInputStream bis = new BufferedInputStream(new FileInputStream("example.txt"))) {
            long bytesSkipped = bis.skip(10);  // Skip the first 10 bytes
            System.out.println("Skipped " + bytesSkipped + " bytes.");
            int byteData;
            while ((byteData = bis.read()) != -1) {
                System.out.print((char) byteData);  // Print the remaining data
            }
        } catch (IOException e) {
            System.out.println("An error occurred during reading.");
            e.printStackTrace();
        }
    }
}

Explanation:

  • The skip() method is used to skip the first 10 bytes in the file.
  • After skipping, the program continues to read the rest of the file and prints the remaining content.

Output:

Skipped 10 bytes.
remaining content of the file after skipping.

Advantages of Using BufferedInputStream

  1. Improved Performance: BufferedInputStream significantly improves the performance of I/O operations by reducing the number of reads from the underlying stream. It reads data into a buffer and provides faster access to that data.

  2. Efficient Memory Usage: Since it uses an internal buffer, it allows more efficient memory management compared to directly reading from an underlying stream one byte at a time.

  3. Reduces Overhead: By reducing the frequency of I/O operations, BufferedInputStream minimizes the overhead of repeatedly accessing slower I/O resources, such as files or network connections.

  4. Support for Mark and Reset: The stream supports marking a position and resetting back to that position, which can be useful when you need to reread parts of the stream.