Readers and Writers — FileReader, FileWriter, BufferedReader, and InputStreamReader
In this tutorial, you will learn about Readers and Writers. We cover key concepts, practical examples, and best practices to help you master this topic.
Java Reader and Writer classes handle character-based I/O, correctly encoding characters to bytes using specified character sets. Unlike byte streams, character streams handle Unicode transparently — they convert between bytes in a specific encoding and Java's internal UTF-16 character representation.
What You'll Learn
- Reader and Writer hierarchy
- FileReader and FileWriter
- BufferedReader for line-oriented input
- InputStreamReader to bridge byte and character streams
- Specifying and understanding character encodings
Why It Matters
Text files have encodings. Reading a UTF-8 file with a platform-default encoding may corrupt non-ASCII characters (accents, CJK, emoji). Understanding Reader/Writer ensures your text I/O works internationally.
Real-World Use
Every text file, CSV parser, log file reader, and web response handler uses character streams. Configuration files, source code, and HTML templates are all text.
Reader and Writer
// Character reading
Reader reader = new FileReader("input.txt");
int charData = reader.read(); // reads one character (0-65535), -1 at end
char[] buffer = new char[1024];
int charsRead = reader.read(buffer);
reader.close();
// Character writing
Writer writer = new FileWriter("output.txt");
writer.write("Hello, World!");
writer.write(buffer, 0, charsRead);
writer.close();
FileReader and FileWriter
// Reading a text file
try (FileReader fr = new FileReader("note.txt")) {
int ch;
while ((ch = fr.read()) != -1) {
System.out.print((char) ch);
}
}
// Writing a text file
try (FileWriter fw = new FileWriter("note.txt")) {
fw.write("Hello, World!\n");
fw.write("Second line");
}
Encoding Issue with FileReader
FileReader uses the platform's default encoding (e.g., UTF-8 on Linux, Windows-1252 on Windows). This is problematic when sharing files across platforms:
// Problem: FileReader uses platform default encoding
// A UTF-8 file may be misread on Windows
FileReader fr = new FileReader("utf8-file.txt");
// Solution: Use InputStreamReader with explicit encoding
Reader reader = new InputStreamReader(
new FileInputStream("utf8-file.txt"),
StandardCharsets.UTF_8
);
BufferedReader and BufferedWriter
BufferedReader provides readLine() for line-oriented reading:
try (BufferedReader br = new BufferedReader(new FileReader("file.txt"))) {
String line;
while ((line = br.readLine()) != null) {
System.out.println("Line: " + line);
}
}
BufferedWriter provides newLine() for platform-independent line breaks:
try (BufferedWriter bw = new BufferedWriter(new FileWriter("output.txt"))) {
bw.write("First line");
bw.newLine();
bw.write("Second line");
}
InputStreamReader and OutputStreamWriter
These bridge byte streams to character streams:
// Reading UTF-8 file through byte stream
try (Reader reader = new InputStreamReader(
new FileInputStream("data.txt"),
StandardCharsets.UTF_8)) {
// read characters
}
// Writing UTF-8 file through byte stream
try (Writer writer = new OutputStreamWriter(
new FileOutputStream("data.txt"),
StandardCharsets.UTF_8)) {
writer.write("Content");
}
Common Encodings
StandardCharsets.UTF_8 // Most common, universal
StandardCharsets.ISO_8859_1 // Latin-1, single byte
StandardCharsets.US_ASCII // 7-bit ASCII
Charset.forName("windows-1252") // Windows Western
Charset.forName("Shift_JIS") // Japanese
Complete Text File Copy
public static void copyTextFile(String source, String dest) throws IOException {
try (BufferedReader reader = new BufferedReader(
new InputStreamReader(new FileInputStream(source), StandardCharsets.UTF_8));
BufferedWriter writer = new BufferedWriter(
new OutputStreamWriter(new FileOutputStream(dest), StandardCharsets.UTF_8))) {
String line;
while ((line = reader.readLine()) != null) {
writer.write(line);
writer.newLine();
}
}
}
PrintWriter
Convenience class for formatted text output:
try (PrintWriter pw = new PrintWriter(
new OutputStreamWriter(new FileOutputStream("output.txt"), StandardCharsets.UTF_8))) {
pw.println("Hello, World!");
pw.printf("Number: %d, String: %s%n", 42, "value");
pw.format("Formatted: %.2f%n", 3.14159);
}
Common Mistakes
- Assuming platform default encoding is UTF-8. On Windows, it is often windows-1252. Always specify the encoding explicitly for portable code.
- Using
FileReader/FileWriterwithout encoding. These use the platform default. UseInputStreamReader/OutputStreamWriterwithStandardCharsetsinstead. - Not buffering character streams. Reading/writing one character at a time is slow. Always wrap with
BufferedReader/BufferedWriter. - Forgetting
newLine()for cross-platform line breaks.BufferedWriter.newLine()uses the platform's line separator. Using\ndirectly may not produce correct line breaks on Windows. - Mixing byte and character streams without bridges. Do not read characters from a
FileInputStreamdirectly — useInputStreamReader.
Practice Questions
1. What is the difference between InputStream and Reader?
InputStream reads bytes. Reader reads characters, handling encoding conversion internally.
2. Why is FileReader problematic for cross-platform applications?
It uses the platform's default encoding, which differs across operating systems. A file written with UTF-8 on Linux may be corrupted when read with FileReader on Windows.
3. How does BufferedReader.readLine() improve performance?
It reads a large block of characters into an internal buffer and serves individual characters or lines from the buffer, reducing the number of native I/O calls.
4. What does OutputStreamWriter do?
It bridges a byte output stream to a character Writer, encoding characters to bytes using a specified charset.
5. How do you write a line separator portably across platforms?
Use BufferedWriter.newLine() or PrintWriter.println().
Challenge Question:
Write a program that counts the number of lines, words, and characters in a text file (like wc on Unix). Use BufferedReader with UTF-8 encoding. Handle edge cases: empty file, file with only whitespace, file with Unicode characters (CJK, emoji). Compare word count between US-ASCII and UTF-8 for accented characters.
FAQ
Mini Project
Write a program TextFileProcessor.java that:
- Reads a UTF-8 encoded text file using
BufferedReaderwrapped aroundInputStreamReader - Counts total lines, words, and characters (including Unicode)
- Finds the longest line and prints its length and content
- Writes an HTML version of the file: wrap each line in
<p>tags, encode HTML entities (<,>,&) - Creates a word frequency map (case-insensitive) and writes the top 10 words to another file
- Demonstrates
PrintWriterfor formatted output - Uses
StandardCharsets.UTF_8for all encoding operations
What's Next
Readers and Writers handle character I/O, but Java NIO.2 provides a more modern file API. Lesson 41 covers NIO.2 Files — the Path class, Files utility methods (walk, find, lines, read/write, copy, move, delete), and the power of the NIO.2 file API.
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro