Java BufferedReader, BufferedWriter & Scanner: High-Performance I/O

Reading disk files byte-by-byte or character-by-character is notoriously slow because every single read triggers a physical disk sector read or OS kernel context switch. Buffered Streams solve this bottleneck by wrapping existing streams with an internal memory buffer (default 8 KB), drastically reducing OS-level system calls.

BufferedReader: High-Speed Line-by-Line Reading

BufferedReader provides the invaluable readLine() method, which reads an entire line of text up to a newline character (\n, \r, or \r\n) and returns it as a String, or null when the end of file is reached.

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.nio.charset.StandardCharsets;

public class FastFileRead {
    public static void main(String[] args) {
        String filePath = "server-logs.txt";
        
        try (BufferedReader reader = new BufferedReader(new FileReader(filePath, StandardCharsets.UTF_8))) {
            String line;
            int lineNumber = 1;
            
            while ((line = reader.readLine()) != null) {
                System.out.printf("[%04d] %s%n", lineNumber++, line);
            }
        } catch (IOException e) {
            System.err.println("Read error: " + e.getMessage());
        }
    }
}

BufferedWriter & PrintWriter: Efficient Writing

BufferedWriter caches outgoing characters in an 8 KB buffer and flushes them to disk when full. PrintWriter wraps writers to provide familiar methods like println() and printf().

import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.PrintWriter;
import java.io.IOException;
import java.nio.charset.StandardCharsets;

public class FastFileWrite {
    public static void main(String[] args) {
        try (FileWriter fw = new FileWriter("students.csv", StandardCharsets.UTF_8, false);
             BufferedWriter bw = new BufferedWriter(fw);
             PrintWriter out = new PrintWriter(bw)) {
            
            out.println("RollNo,Name,Course,Grade");
            out.printf("%d,%s,%s,%.1f%n", 101, "Aarav Sharma", "BCA", 92.5);
            out.printf("%d,%s,%s,%.1f%n", 102, "Neha Patel", "MCA", 88.0);
            out.printf("%d,%s,%s,%.1f%n", 103, "Rohan Verma", "B.Tech", 95.2);
            
            System.out.println("CSV export completed successfully.");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

Scanner vs BufferedReader: Detailed Benchmark

FeatureBufferedReaderScanner
PurposeRaw, high-speed character stream readingParsing primitives & tokens using Regex
Buffer Size8,192 characters (8 KB)1,024 characters (1 KB)
SynchronizationSynchronized (Thread-Safe)Not Synchronized (Not Thread-Safe)
Execution SpeedExtremely Fast (~10x faster)Slower due to Regex tokenization overhead
Exception HandlingRequires throws IOException or try-catchHides IOException (checks ioException())
Best Used ForLarge files, competitive programming, bulk logsInteractive CLI user input parsing (integers, strings)

Dry-Run & Memory Execution Trace

Trace: BufferedReader.readLine() Loop Execution
Iterationreader.readLine() Resultline VariableLoop ConditionAction Taken
1"101,Aarav Sharma,BCA,92.5"Points to String on Heap!= null (TRUE)Prints formatted line 1
2"102,Neha Patel,MCA,88.0"Points to String on Heap!= null (TRUE)Prints formatted line 2
3"103,Rohan Verma,B.Tech,95.2"Points to String on Heap!= null (TRUE)Prints formatted line 3
4null (EOF)null!= null (FALSE)Loop exits; try-with-resources closes buffer & stream
BCA / University Exam Corner
  • Viva Question: Why should we avoid using Scanner in competitive programming when input exceeds 100,000 lines?
    Answer: Scanner uses regular expressions internally for every nextInt() or next() call and has a small 1 KB buffer. On large datasets, this causes severe Time Limit Exceeded (TLE) errors. BufferedReader coupled with StringTokenizer is the standard fast I/O pattern.
  • Key Method: Remember bw.newLine() writes a platform-independent newline separator (\r\n on Windows, \n on UNIX).

Frequently Asked Questions (FAQ)

Q1. Why is BufferedReader significantly faster than standard FileReader or Scanner?
Standard FileReader executes a physical operating system read call for every single character, causing costly kernel context switches. BufferedReader maintains an internal 8,192-character (8 KB) memory buffer, reading large blocks from the disk in a single system call and serving subsequent read requests directly from fast RAM.
Q2. What is the key difference between Scanner and BufferedReader?
Scanner is a high-level utility used for parsing formatted tokens (integers, doubles, strings) via regular expressions with a small 1 KB buffer. BufferedReader is a low-level, synchronized reader with a large 8 KB buffer that simply reads raw lines (readLine()) without parsing, making it up to 10x faster for large text files.
Q3. What happens if we do not invoke flush() or close() on a BufferedWriter?
Data written to BufferedWriter is temporarily staged in the internal memory buffer. If flush() or close() is omitted, remaining data in the buffer may never be committed to disk, causing truncated or completely blank output files.

Explore Related Java Tutorials

Accelerate your Java mastery by studying these tightly connected core tutorials:

File I/O Streams →

Core Byte and Character stream fundamentals.

Java NIO.2 Files →

Modern Files.readAllLines() and Files.lines().

Try-with-Resources →

Automatic stream flushing and closing.

Java Strings & Parsing →

String splitting and token processing.

Share Share on Facebook Share on Twitter Share on LinkedIn Pin on Pinterest Share on Stumbleupon Share on Tumblr Share on Reddit Share on Diggit

You may also like this!