Java Notes
Complete guide to Character Streams in Java — FileReader, FileWriter, handling Unicode text, character encoding, reading/writing text files with proper internationalization support.
What are Character Streams?
Character streams handle I/O of character (text) data. They automatically handle the translation between bytes and characters using a character encoding (like UTF-8, UTF-16).
Why Not Just Use Byte Streams for Text?
Output:
| Original text | Hello 日本語 العربية 한국어 |
| UTF-8 bytes | 37 bytes |
| UTF-16 bytes | 44 bytes |
| Characters | 20 chars |
| Read back | Hello 日本語 العربية 한국어 |
Character Stream Hierarchy
FileWriter — Writing Text
import java.io.FileWriter;
import java.io.IOException;
public class FileWriterExample {
public static void main(String[] args) {
System.out.println("=== FileWriter Examples ===\n");
// Method 1: Write strings
try (FileWriter writer = new FileWriter("story.txt")) {
writer.write("Once upon a time in Java land...\n");
writer.write("There lived a programmer who loved clean code.\n");
writer.write("The End.\n");
System.out.println("✓ Written story to file");
} catch (IOException e) {
System.out.println("Error: " + e.getMessage());
}
// Method 2: Write characters
try (FileWriter writer = new FileWriter("chars.txt")) {
writer.write('H');
writer.write('i');
writer.write('!');
writer.write('\n');
System.out.println("✓ Written individual characters");
} catch (IOException e) {
System.out.println("Error: " + e.getMessage());
}
// Method 3: Write char array
try (FileWriter writer = new FileWriter("array.txt")) {
char[] greeting = {'H', 'e', 'l', 'l', 'o', '!', '\n'};
writer.write(greeting);
// Write partial array
char[] data = "Java Programming".toCharArray();
writer.write(data, 5, 11); // "Programming"
System.out.println("✓ Written char arrays");
} catch (IOException e) {
System.out.println("Error: " + e.getMessage());
}
// Method 4: Append mode
try (FileWriter writer = new FileWriter("story.txt", true)) {
writer.write("\n--- Sequel ---\n");
writer.write("The programmer discovered streams...\n");
System.out.println("✓ Appended to story");
} catch (IOException e) {
System.out.println("Error: " + e.getMessage());
}
// Cleanup
new java.io.File("story.txt").delete();
new java.io.File("chars.txt").delete();
new java.io.File("array.txt").delete();
}
}FileReader — Reading Text
Output:
| Chunk 1 (20 chars) | 'Roses are red,\nViole' |
| Chunk 2 (20 chars) | 'ts are blue,\nJava is' |
| Chunk 3 (20 chars) | ' awesome,\nAnd so are' |
| Chunk 4 (8 chars) | ' you!\n' |
Character Encoding with InputStreamReader / OutputStreamWriter
FileReader and FileWriter use the system's default encoding. For explicit encoding control, use the bridge classes:
Output:
| Text | Héllo Wörld! 你好世界 🌍 |
| Read UTF-8 | Héllo Wörld! 你好世界 🌍 |
| Encoding used | UTF8 |
| Read Latin-1 | H?llo W?rld! ???? ?? |
| UTF-8 | 29 bytes |
| Latin-1 | 19 bytes |
PrintWriter — Convenient Text Output
import java.io.*;
public class PrintWriterExample {
public static void main(String[] args) throws IOException {
System.out.println("=== PrintWriter Demo ===\n");
try (PrintWriter pw = new PrintWriter(new FileWriter("report.txt"))) {
// Like System.out but writes to file!
pw.println("=== Sales Report ===");
pw.println();
pw.printf("%-15s %10s %10s%n", "Product", "Qty", "Revenue");
pw.println("-".repeat(37));
pw.printf("%-15s %10d %10.2f%n", "Laptop", 150, 224999.50);
pw.printf("%-15s %10d %10.2f%n", "Mouse", 500, 7499.00);
pw.printf("%-15s %10d %10.2f%n", "Keyboard", 300, 14997.00);
pw.println("-".repeat(37));
pw.printf("%-15s %10d %10.2f%n", "TOTAL", 950, 247495.50);
pw.println();
pw.print("Generated: ");
pw.println(java.time.LocalDateTime.now());
// Check for errors (PrintWriter doesn't throw exceptions!)
if (pw.checkError()) {
System.out.println("Warning: Write error occurred!");
}
}
// Read and display
try (BufferedReader reader = new BufferedReader(new FileReader("report.txt"))) {
String line;
while ((line = reader.readLine()) != null) {
System.out.println(line);
}
}
new File("report.txt").delete();
}
}Output:
Real-World Example: CSV File Handler
Output:
Byte Stream vs Character Stream Comparison
Common Mistakes
1. Using FileReader/FileWriter for binary files
// ❌ WRONG: Will corrupt binary data (images, PDFs, etc.)
FileReader reader = new FileReader("image.png");
// ✅ CORRECT: Use byte streams for binary
FileInputStream fis = new FileInputStream("image.png");2. Ignoring character encoding
// ❌ BAD: Uses platform default encoding (unpredictable)
FileWriter writer = new FileWriter("data.txt");
// ✅ GOOD: Specify encoding explicitly
OutputStreamWriter writer = new OutputStreamWriter(
new FileOutputStream("data.txt"), StandardCharsets.UTF_8);
// ✅ BETTER (Java 11+):
Files.writeString(Path.of("data.txt"), content, StandardCharsets.UTF_8);3. Not flushing before close
// ✅ Try-with-resources handles this automatically
try (FileWriter writer = new FileWriter("file.txt")) {
writer.write("data");
} // flush + close called automaticallyInterview Questions
Q1: What is the difference between byte stream and character stream?
Answer: Byte streams (InputStream/OutputStream) work with raw bytes (8-bit) and are suitable for all file types. Character streams (Reader/Writer) work with characters (16-bit Unicode) and handle encoding/decoding automatically, making them ideal for text processing.
Q2: What is InputStreamReader? Why is it called a "bridge"?
Answer: InputStreamReader converts a byte stream (InputStream) into a character stream (Reader). It's called a bridge because it connects the two stream hierarchies, reading bytes from the underlying InputStream and decoding them into characters using a specified charset.
Q3: What encoding does FileReader use by default?
Answer: It uses the platform's default charset (e.g., UTF-8 on Linux, Cp1252 on Windows). Since Java 18, the default is UTF-8 on all platforms. For portability, always specify encoding explicitly using InputStreamReader with a charset.
Q4: Can FileWriter handle Unicode characters like Chinese or emoji?
Answer: Yes, if the file's encoding supports them. FileWriter uses the platform's default encoding. If that's UTF-8, it handles all Unicode. But on some Windows systems with default Latin-1 encoding, non-Latin characters will be corrupted. Always specify UTF-8 explicitly for international text.
Q5: Why should you prefer BufferedReader over FileReader directly?
Answer: FileReader reads from disk one character at a time (one system call per read). BufferedReader wraps FileReader with an internal buffer (default 8KB), dramatically reducing disk I/O. It also provides readLine() method for line-by-line reading.
Exam Focus
Revise definitions, diagrams, examples, and short-answer points for Character Streams in Java.
Interview Use
Prepare one clear explanation, one practical example, and one common mistake for this Java Master Course topic.
Search Terms
java-master-course, java master course, java, master, course, file, handling, character
Related Java Master Course Topics