About Us Contact Us Write for Us Advertise
Home > Java > File I/O in Java: Reading and Writing Files the Modern Way
Java

File I/O in Java: Reading and Writing Files the Modern Way

Learn file input/output in Java with the modern Files and Path API — read and write text, handle IOException, and use try-with-resources to close files safely.

Shiv Pandey
Shiv Pandey
Sep 26, 2026 | 2 views
File I/O in Java: Reading and Writing Files the Modern Way

Programs become far more useful when they can remember things between runs — save a report, read a config file, log what happened. That means working with files. In this lesson you'll learn the modern, clean way to read and write files in Java, plus the one safety habit that prevents a whole class of bugs. It's more practical than intimidating, promise.

Reading and writing: the modern way

Older Java file code was verbose and fiddly. Modern Java (via the java.nio.file package) makes the common cases wonderfully short. Meet Files and Path:

Writing a file

import java.nio.file.*;

Path path = Path.of("notes.txt");
Files.writeString(path, "Hello from Java!\nSecond line.");   // done — file written

Reading a file

// whole file as one String
String content = Files.readString(Path.of("notes.txt"));
System.out.println(content);

// or line by line into a List
List<String> lines = Files.readAllLines(Path.of("notes.txt"));
for (String line : lines) {
    System.out.println(line);
}

That's genuinely all you need for most everyday file work. Files.writeString, Files.readString, and Files.readAllLines cover a huge amount of ground.

Files operations are "checked" — you must handle IOException

Remember checked exceptions from the exceptions lesson? File operations can fail for reasons outside your control — the file might be missing, locked, or the disk full — so Java forces you to handle an IOException. Wrap file code in a try-catch:

try {
    String content = Files.readString(Path.of("notes.txt"));
    System.out.println(content);
} catch (IOException e) {
    System.out.println("Could not read the file: " + e.getMessage());
}

Reading larger files with a reader

For big files you don't want to load entirely into memory. A BufferedReader reads line by line efficiently — and here's where the safety habit comes in:

// try-with-resources: the reader is closed for you automatically
try (BufferedReader reader = Files.newBufferedReader(Path.of("big.txt"))) {
    String line;
    while ((line = reader.readLine()) != null) {
        System.out.println(line);
    }
} catch (IOException e) {
    e.printStackTrace();
}
The golden habit: try-with-resources. Notice the resource declared inside try (...). Files, readers, and database connections must be closed when you're done, or you'll leak resources. Try-with-resources closes them automatically — even if an exception occurs. Always open files this way and you'll never forget to close one. This is the modern replacement for manually calling .close() in a finally block.

Checking and creating files

The Files class has handy helpers for common checks:

Path p = Path.of("data.txt");

Files.exists(p);            // true/false
Files.createFile(p);        // create a new empty file
Files.createDirectories(Path.of("logs/2026"));   // make folders
Files.delete(p);            // delete it

File I/O is one of those skills you reach for constantly once you know it — reading a config, exporting a report, appending to a log. The habit I'd most urge you to lock in early is try-with-resources: I've debugged real problems caused by files and connections left open, and this single pattern makes that mistake impossible. Learn the short Files methods for the easy cases and always open resources in a try (...), and you've got file handling covered.

Key takeaways

  • Modern file I/O uses Files + Path: writeString, readString, readAllLines.
  • File operations throw checked IOException — you must try-catch them.
  • Always use try-with-resources (try (Reader r = ...)) so files/streams close automatically.
  • Files also offers exists, createFile, createDirectories, delete.

← Previous: Lesson 30 — Multithreading in Java
Next: Lesson 32 — Date & Time API →

Related Articles

The Streams API in Java: Process Collections the Modern Way
Java

The Streams API in Java: Process Collections the Modern Way

Optional in Java: A Safer Way to Handle Missing Values
Java

Optional in Java: A Safer Way to Handle Missing Values

Constructors in Java: Setting Up Objects the Right Way
Java

Constructors in Java: Setting Up Objects the Right Way

Input and Output in Java: Reading User Input with Scanner
Java

Input and Output in Java: Reading User Input with Scanner