File I/O

File I/O (input/output) is how a Java program reads data from files on disk and writes data back to them. Java's standard library offers a few different ways to do this — this page covers the classic BufferedReader/FileWriter approach and the more modern java.nio.file.Files alternative.

Reading a Text File

The traditional way to read a text file line by line is to wrap a FileReader in a BufferedReader. The buffer reduces the number of slow, individual reads from disk by reading larger chunks at once.

Example: Reading Line by Line

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;

public class ReadFileDemo {
  public static void main(String[] args) {
    try (BufferedReader br = new BufferedReader(new FileReader("notes.txt"))) {
      String line;
      while ((line = br.readLine()) != null) {
        System.out.println(line);
      }
    } catch (IOException e) {
      System.out.println("Could not read file: " + e.getMessage());
    }
  }
}

try-with-resources

Notice the try (BufferedReader br = ...) { } syntax above — this is called try-with-resources. Any resource opened inside the parentheses is automatically closed when the block finishes, whether it finishes normally or via an exception. Before this syntax existed, closing file handles required a manual finally block, and it was easy to forget — leaving files locked or leaking resources.

Note: File operations declare a checked IOException, which the compiler forces you to either catch or declare with throws. This is Java's way of making sure you don't ignore the very real possibility that a file is missing, locked, or unreadable.

Writing to a Text File

Writing follows the same pattern in reverse — FileWriter handles the raw writing, and wrapping it in a BufferedWriter batches up writes for better performance.

try (BufferedWriter bw = new BufferedWriter(new FileWriter("notes.txt"))) {
  bw.write("Learning Java File I/O");
  bw.newLine();
  bw.write("try-with-resources closes this automatically");
} catch (IOException e) {
  System.out.println("Could not write file: " + e.getMessage());
}
          

The Modern Alternative: java.nio.file.Files

More recent Java versions offer java.nio.file.Files, which handles a lot of the boilerplate above in a single line. For smaller files, this is often easier to reach for than manually managing readers and writers.

import java.nio.file.Files;
import java.nio.file.Path;

List<String> lines = Files.readAllLines(Path.of("notes.txt"));

Files.write(Path.of("output.txt"), List.of("line one", "line two"));
          

What's happening:

  • Files.readAllLines() reads the entire file and returns every line as a List<String> — no manual loop needed.
  • Files.write() writes a list of lines to a file in one call, creating the file if it doesn't already exist.
  • These methods still throw IOException, so the same checked-exception rules apply.
Next up: write more compact, readable code with Lambdas & Streams.