Buffered Streams in Java
Buffered streams are wrapper streams that add a buffer, a block of memory, between your program and the underlying stream. Instead of going to the disk for every single byte or character, a buffered stream reads or writes a large block at once (8 KB by default) and serves your small requests from memory. This makes I/O much faster. The four classes are BufferedInputStream, BufferedOutputStream, BufferedReader and BufferedWriter. In this lesson, you will learn how to use them and measure the difference they make.
How Buffering Works
The Buffered Classes
| Class | Wraps | Extra methods |
|---|---|---|
BufferedInputStream | Any InputStream | mark, reset |
BufferedOutputStream | Any OutputStream | None (just faster) |
BufferedReader | Any Reader | readLine(), lines() |
BufferedWriter | Any Writer | newLine() |
You create one by wrapping another stream: new BufferedReader(new FileReader("a.txt")).
Example: Reading Lines with BufferedReader
Let's see an example that writes and reads a file line by line.
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
public class Lines {
public static void main(String[] args) throws IOException {
try (BufferedWriter w = new BufferedWriter(
new FileWriter("marks.csv", StandardCharsets.UTF_8))) {
w.write("Navika,91");
w.newLine();
w.write("Srihitha,78");
w.newLine();
w.write("Advitha,85");
w.newLine();
}
int total = 0;
try (BufferedReader r = new BufferedReader(
new FileReader("marks.csv", StandardCharsets.UTF_8))) {
String line;
while ((line = r.readLine()) != null) {
String[] parts = line.split(",");
System.out.println(parts[0] + " scored " + parts[1]);
total += Integer.parseInt(parts[1]);
}
}
System.out.println("Total: " + total);
}
}Navika scored 91
Srihitha scored 78
Advitha scored 85
Total: 254Explanation: BufferedWriter.newLine() writes the correct line ending for the operating system. BufferedReader.readLine() returns one line at a time without its line ending, and null at the end of the file. Both streams collect data in memory and touch the disk only in large blocks.
The Checkpoint: Measuring the Speed-Up
This program copies a 2 MB binary file twice, first one byte at a time with plain streams, then with buffered streams, and compares the times. Times depend on the computer, so the output is a sample.
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Random;
public class CopySpeed {
static long copy(InputStream in, OutputStream out) throws IOException {
long start = System.nanoTime();
int b;
while ((b = in.read()) != -1) {
out.write(b);
}
return (System.nanoTime() - start) / 1_000_000;
}
public static void main(String[] args) throws IOException {
byte[] data = new byte[2_000_000];
new Random(1).nextBytes(data);
try (OutputStream out = new FileOutputStream("photo.bin")) {
out.write(data);
}
long plain;
try (InputStream in = new FileInputStream("photo.bin");
OutputStream out = new FileOutputStream("copy1.bin")) {
plain = copy(in, out);
}
long buffered;
try (InputStream in = new BufferedInputStream(
new FileInputStream("photo.bin"));
OutputStream out = new BufferedOutputStream(
new FileOutputStream("copy2.bin"))) {
buffered = copy(in, out);
}
System.out.println("Unbuffered: " + plain + " ms");
System.out.println("Buffered: " + buffered + " ms");
}
}Unbuffered: 3787 ms
Buffered: 20 msExplanation: The same copy method runs twice. Without buffering, each read() and write() is a separate request to the operating system: 4 million system calls. With buffering, the streams move 8 KB at a time, so the same loop makes only about 500 system calls and finishes hundreds of times faster.
Common Mistakes
Forgetting to close or flush a BufferedWriter. The last block may stay in memory and never reach the file.
Wrapping a buffered stream in another buffered stream. It wastes memory without making anything faster.
Using Scanner for very large files. BufferedReader is faster for plain line reading (see "Scanner vs BufferedReader").
Interview Corner
Why are buffered streams faster?
Each read or write on an unbuffered file stream can become a separate system call, which is expensive. A buffered stream keeps an internal array (8 KB by default): reads fill the array with one large system call and then serve many small reads from memory, and writes collect data in the array and send it in one large call when it fills or is flushed. This greatly reduces the number of system calls, especially when the program reads or writes a byte, character or line at a time.
Practice
- Easy: Read a text file with
BufferedReaderand print only the lines that contain the word "Java". - Harder: Change
CopySpeedto also time a copy usingin.transferTo(out)with plain file streams. Explain why it's fast without buffered wrappers.
Key Takeaways
Was this tutorial helpful?