In Java, the BufferedInputStream and BufferedOutputStream classes are used to improve the efficiency of input and output operations by adding a buffer between the program and the input/output source (such as a file or network connection). By buffering the data, fewer I/O operations are performed, which can significantly improve performance, especially for reading and writing large amounts of data.
A buffer is a temporary storage area in memory that holds data before it is processed. Instead of reading or writing data byte-by-byte (which can be slow), a buffer reads or writes data in larger blocks, minimizing the number of interactions with the underlying system (such as a hard drive).
BufferedInputStream is a subclass of FilterInputStream and adds buffering to an input stream. It wraps around other input streams, such as FileInputStream, and provides efficient reading of data by reducing the number of I/O operations.
Constructors of BufferedInputStream:
BufferedInputStream(InputStream in)
BufferedInputStream(InputStream in, int size) // in: input stream, size: buffer sizeimport java.io.BufferedInputStream;import java.io.FileInputStream;import java.io.IOException;public class BufferedInputStreamExample { public static void main(String[] args) { try (BufferedInputStream bis = new BufferedInputStream(new FileInputStream("example.txt")){ int data; while ((data = bis.read()) != -1) { System.out.print((char) data); // Convert byte to character } } catch (IOException e) { e.printStackTrace(); } }}Explanation:
BufferedInputStream: Wraps the FileInputStream, adding a buffer for efficient reading.bis.read(): Reads data from the buffer instead of directly from the file, improving performance.example.txt character by character.BufferedOutputStream is a subclass of FilterOutputStream and adds buffering to an output stream. It wraps around other output streams, such as FileOutputStream, and writes data to the buffer first, then to the destination when the buffer is full or explicitly flushed.
BufferedOutputStream collects the data in a buffer. When the buffer is full (default size is 8 KB) or explicitly flushed, it writes the entire buffer to the output stream in one operation, reducing the number of writes.Constructors of BufferedOutputStream:
BufferedOutputStream(OutputStream out)
BufferedOutputStream(OutputStream out, int size) // out: output stream, size: buffer sizexxxxxxxxxximport java.io.BufferedOutputStream;import java.io.FileOutputStream;import java.io.IOException;public class BufferedOutputStreamExample { public static void main(String[] args) { try (BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("output.txt"))) { String data = "BufferedOutputStream improves writing efficiency!"; bos.write(data.getBytes()); // Convert string to bytes and write to buffer bos.flush(); // Ensure all buffered data is written to the file } catch (IOException e) { e.printStackTrace(); } }}Explanation:
BufferedOutputStream: Wraps the FileOutputStream, adding a buffer for efficient writing.bos.write(): Writes data to the buffer instead of directly to the file.bos.flush(): Ensures that any remaining data in the buffer is written to the file.output.txt.Without buffering, every read() or write() operation would result in an I/O operation, which is relatively slow. Buffering minimizes these I/O operations by grouping them into larger chunks, thereby improving the program's performance.
read(): Reads a single byte from the input stream.read(byte[] b, int off, int len): Reads bytes into the specified portion of the byte array.available(): Returns an estimate of the number of bytes that can be read without blocking.mark(int readlimit): Marks the current position in the input stream for later resetting.reset(): Resets the input stream to the previously marked position.close(): Closes the stream and releases system resources.write(int b): Writes a single byte to the output stream.write(byte[] b, int off, int len): Writes bytes from the specified byte array to the output stream.flush(): Forces any buffered output bytes to be written to the underlying output stream.close(): Closes the stream, flushing any remaining buffered output.| Feature | FileInputStream / FileOutputStream | BufferedInputStream / BufferedOutputStream |
|---|---|---|
| Performance | Slower, as data is read/written byte-by-byte | Faster, as data is read/written in larger chunks (buffered) |
| Default Buffer Size | No buffering by default | 8192 bytes (8 KB), can be customized |
| Use Case | Suitable for small amounts of data | Suitable for large amounts of data, improves performance |
| Typical Operations | Direct access to file or network stream | Buffered access to file or network stream |
Copying a File Using Buffered Streams
This example demonstrates copying a file using BufferedInputStream and BufferedOutputStream to improve efficiency.
xxxxxxxxxximport java.io.BufferedInputStream;import java.io.BufferedOutputStream;import java.io.FileInputStream;import java.io.FileOutputStream;import java.io.IOException;public class BufferedCopyFileExample { public static void main(String[] args) { try ( BufferedInputStream bis = new BufferedInputStream(new FileInputStream("sourceFile.txt")); BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("destinationFile.txt"))){ byte[] buffer = new byte[1024]; // Buffer size is 1024 bytes (1 KB) int bytesRead; // Read from the source file into the buffer while ((bytesRead = bis.read(buffer)) != -1) { // Write the buffer contents to the destination file // 0 is the starting index bos.write(buffer, 0, bytesRead); } } catch (IOException e) { e.printStackTrace(); } }}Explanation:
BufferedInputStream: Reads data from sourceFile.txt in chunks, improving the efficiency of reading.BufferedOutputStream: Writes data to destinationFile.txt in chunks, improving the efficiency of writing.