Java File I/O — Introduction

1 minute read

Almost every real-world Java application needs to read from or write to files — configuration files, logs, CSV data exports, JSON API responses, or user uploads. Java provides two main packages for file I/O: the classic java.io (since Java 1.0) and the modern java.nio.file (since Java 7).

In this chapter, you’ll learn the landscape of Java I/O, understand the key abstractions, and know when to use which approach.


java.io vs java.nio

Feature java.io (classic) java.nio.file (modern)
Introduced Java 1.0 (1996) Java 7 (2011)
API style Stream-based (InputStream, OutputStream) Path-based (Path, Files)
Blocking? Yes (blocking I/O) Supports non-blocking (NIO channels)
File operations Basic (read, write, delete) Rich (walk, find, copy, move, watch)
Recommendation Use for legacy code Use for all new code

Rule of thumb: Use java.nio.file.Files and java.nio.file.Path for all new file operations. Fall back to java.io only when a library requires it.


Byte Streams vs Character Streams

Java distinguishes between binary data (bytes) and text data (characters):

  Byte Streams Character Streams
Base classes InputStream / OutputStream Reader / Writer
Unit byte (8 bits) char (16 bits, Unicode)
Use for Images, PDFs, binary files Text files, CSV, JSON, XML
Examples FileInputStream, BufferedInputStream FileReader, BufferedReader

Always Close Your Resources

File handles are limited system resources. Always close them after use. The modern way is try-with-resources:

// ✅ Good — automatically closes the reader
try (BufferedReader reader = new BufferedReader(new FileReader("data.txt"))) {
    String line;
    while ((line = reader.readLine()) != null) {
        System.out.println(line);
    }
}
// reader is automatically closed here, even if an exception occurs

What’s Next?

In the next chapter, you’ll learn how to read files using both classic BufferedReader and modern Files.readString().

Updated: