Blog

FileReader vs BufferedReader vs Scanner | Java

Update: If you're looking for a real-world use case on the following material, check out how to read a CSV file in Java.


FileReader, BufferedReader, and Scanner are all classes for handling I/O in Java.

To understand what makes them different, it's important to know the distinctions between byte streams, character streams, and buffered streams.

Key Takeaways

  • Byte streams manage raw bytes, while character streams are tailored for character data with encoding support.
  • Buffered streams improve I/O efficiency by reducing interactions with the underlying OS.
  • FileReader handles character streams unbuffered; BufferedReader adds buffering for performance.
  • Scanner offers parsing capabilities, including regex, beyond basic character and byte reading.

Byte Streams

Byte streams read bytes of data from an input, like text or audio files. They extend from InputStream or OutputStream and provide foundational I/O operations without nuanced data processing.

Character Streams

Character streams are built on byte streams and provide character encoding, which is essential when working with text data. They descend from Reader or Writer. Examples include FileReader and FileWriter.

Buffered Streams

Both byte and character streams, by default, are unbuffered, meaning they engage with the file system one byte at a time. This is inefficient due to slower disk access speeds compared to memory operations.

Buffered streams mitigate this by reading/writing many bytes at a time into a memory buffer. Streams like BufferedReader or BufferedWriter are examples of buffered character streams, while BufferedInputStream and BufferedOutputStream represent buffered byte streams.

FileReader vs BufferedReader

FileReader is a straightforward character stream without buffering. As it processes each character independently, this can impact performance negatively for large files.

To enhance I/O efficiency, wrap FileReader in a BufferedReader:

BufferedReader reader = new BufferedReader(new FileReader("data.txt"));
reader.readLine();

Besides performance, BufferedReader offers methods like readLine() that are absent in FileReader.

BufferedReader vs InputStreamReader

InputStreamReader bridges byte streams and character streams. It's useful for specifying character encodings, such as UTF-8.

While FileReader automatically assumes system default encoding, InputStreamReader gives you control over this, making it versatile for international applications. A common setup involves wrapping an InputStreamReader in a BufferedReader to maximize reading efficiency.

BufferedReader vs Scanner

Scanner is more than a reader; it's a parsing tool using regular expressions. While BufferedReader reads data efficiently, Scanner excels in parsing tokens from input streams.

Scanner scanner = new Scanner(new BufferedReader(new FileReader("data.txt")));

While BufferedReader is synchronous, Scanner lacks this property, making the former more predictable in multithreaded environments.

FAQ

Can I use BufferedReader with different character encodings?

Yes, by wrapping an InputStreamReader in a BufferedReader, you can specify various encodings, such as UTF-8.

When should I prefer Scanner over BufferedReader?

Use Scanner when you need to parse and process tokens, especially with complex delimiters, while BufferedReader is suitable for simple, efficient reading.

Is there a significant performance difference between BufferedReader and FileReader?

Yes, BufferedReader significantly enhances performance by reducing I/O operations via buffering, making it ideal for large files.

Does Scanner support synchronization like BufferedReader?

No, Scanner is not synchronized, making BufferedReader a better choice in environments requiring thread safety.

Mastering the tech interviewWhat everyone is doing wrong in tech interviews