File Handling / Java I/O
The java.io package gives tools for working with files — FileReader/FileWriter for characters, BufferedReader for fast line-by-line reading.
try-with-resources automatically closes a resource once the block finishes — it protects you from the mistake of leaving a file/connection open.
try (BufferedReader br = new BufferedReader(new FileReader("notes.txt"))) {
String line = br.readLine();
System.out.println(line);
} catch (IOException e) {
System.out.println("File error: " + e.getMessage());
}- FileReader/Writer = reading/writing characters
- BufferedReader = fast line-by-line reading
- try-with-resources = auto-close
Java I/O splits into two families: Streams (InputStream/OutputStream) for raw bytes — images, videos, any binary data, where there's no concept of encoding (just 0s and 1s). Readers/Writers (FileReader/FileWriter) are specifically for characters/text — they automatically handle encoding (UTF-8 etc.), so special characters (like Hindi text) are read/written correctly.
Rule of thumb: use Reader/Writer for text files (.txt, .csv, .java), and use Stream for binary files (.jpg, .mp3, .zip).
| Streams | Readers/Writers | |
|---|---|---|
| Data type | Raw bytes | Characters (text) |
| Handles encoding? | No | Yes (UTF-8, etc.) |
| Example classes | FileInputStream, FileOutputStream | FileReader, FileWriter |
| When to use | Images, videos, binary | Text files |
FileWriter writes directly to the file — every write() call goes to disk, which can be slow if you're writing in small pieces repeatedly. BufferedWriter wraps it to boost performance — it collects data in a memory buffer and writes to disk all at once (repeated disk access is expensive, memory access is cheap).
newLine() gives a platform-independent line break (Windows and Linux/Mac have different line-ending characters — \r\n vs \n — newLine() handles this automatically for you).
try (BufferedWriter bw = new BufferedWriter(new FileWriter("notes.txt"))) {
bw.write("Hello Java!");
bw.newLine();
bw.write("Second line");
}Java 7+ gave us the java.nio.file.Files class, which offers a much simpler, modern API — Files.readAllLines(path) reads the whole file into a List<String> in one line (perfect for small-to-medium files, since the entire content fits in memory). Files.write(path, lines) writes it.
There are also utility methods like Files.exists(path), Files.delete(path), Files.copy(source, target) that used to need a lot more code with the old java.io API.
List<String> lines = Files.readAllLines(Paths.get("notes.txt"));
Files.write(Paths.get("output.txt"), lines);
System.out.println(Files.exists(Paths.get("notes.txt"))); // true/falseFile operations (missing file, permission denied, disk full, network drive disconnected) can throw an IOException — it's a checked exception, so handling it is mandatory (the compiler will force you).
Use try-with-resources so the file closes automatically (whether an exception occurs or not), and give a meaningful error message in the catch block, don't silently ignore it — tell the user exactly what went wrong (like "Could not find notes.txt" instead of a generic "An error occurred").