Chapter 16 of 16Foundation

Optional: File I/O and Serialization

Read and write files with the Files API, and understand why native Java serialization is legacy material.

25 minJava 21
01

Why it matters

Start from the concept, not the syntax

Meet a concrete situation where this idea earns its place, then state the boundary it guards.

Programs that matter read and write data. The stream and reader abstractions handle bytes and text uniformly, the Files API turns common operations into one-liners, and serialization shows why explicit formats usually beat implicit ones.

By the end of this chapter

Leaving streams open or relying on the platform encoding corrupts data and exhausts file handles under load.

  • Reader and Writer
  • Path and Files
  • Serialization trade-offs
02

Mechanism

How Java expresses the concept

Walk the actual types, rules, and runtime behavior involved—the same behavior described in the Java Language Specification.

The mental model

Byte streams (`InputStream`/`OutputStream`) move raw bytes; character streams (`Reader`/`Writer`) move text and handle encoding. Wrap a `Reader` in a `BufferedReader` for efficient line-by-line reading. Always close streams, ideally with try-with-resources.

The `java.nio.file` API centers on `Path` and `Files`: `Files.readString`, `Files.writeString`, `Files.lines` for streaming lines, and `Files.walk` for trees. Prefer these over the legacy `File` methods; they are clearer and throw specific, catchable exceptions.

Serialization turns an object graph into bytes via `ObjectOutputStream` and rebuilds it with `ObjectInputStream`. The class must implement `Serializable` (a marker interface) and ideally declare a `serialVersionUID`. Treat Java native serialization as legacy: it is brittle across versions and a security risk, so prefer JSON or another explicit format for new code.

Text encoding matters. Decode and encode with an explicit `Charset` (UTF-8) instead of relying on the platform default, or the same file can read differently on another machine.

03

Concept map

Inspect the building blocks as a whole

Use the map as a structural reference; it shows the pieces and their relationships, not an execution sequence.

Core Java

File I/O and serialization

Files are read through streams and readers. Modern Java adds `Files` and `Path`; older code uses `FileReader` and `BufferedReader`.

  1. 01Byte vs character streams
  2. 02BufferedReader lines
  3. 03Path and Files
  4. 04Serializable marker
  5. 05serialVersionUID
  6. 06Always close streams
04

Implementation

Encode the smallest runnable example

Write and run the code, then observe the behavior you just predicted with a real Java program.

Runnable snippet path

Predict, run, and change each example

2 focused examples
01

Read all lines

Files.lines streams lines and closes the file automatically via try-with-resources.

Lines.java
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;

public class Lines {
    static long count(Path p) throws IOException {
        try (var stream = Files.lines(p)) {
            return stream.count();
        }
    }
}

Remember

Pass an explicit Charset when reading text so encoding is not left to the platform.

Change one input, predict the result, then compile or test it before continuing.

02

Write a serializable object

Implement Serializable and declare a UID; write and read through object streams.

Save.java
import java.io.*;

class Point implements Serializable {
    private static final long serialVersionUID = 1L;
    final int x, y;
    Point(int x, int y) { this.x = x; this.y = y; }
}

class Save {
    static void save(Point p, String file) throws IOException {
        try (var out = new ObjectOutputStream(new FileOutputStream(file))) {
            out.writeObject(p);
        }
    }
}

Remember

Native serialization is legacy; prefer JSON for new systems.

Change one input, predict the result, then compile or test it before continuing.

05

Watch out

Break it on purpose, then repair the right layer

Predict the symptom before running the failure case, and close with the completion checklist.

Deliberate failure

  1. Break

    Read a file without closing the stream and without pinning an encoding

  2. Observe

    Handles leak over time and the same text decodes differently on another machine

  3. Repair

    Close every stream with try-with-resources and pass an explicit UTF-8 charset for all text I/O

Why it matters

Close every stream with try-with-resources and pass an explicit UTF-8 charset for all text I/O

Completion checklist

  • Read and write text safely with explicit encoding
  • Use Path and Files for file operations
  • Explain Serializable and its limits
06

Go deeper

Official references

The primary sources behind this chapter. Every claim above stays consistent with them.