Streams That Hold a Resource

Streams · lesson 37 of 42 · 3 min read

Files.lines opens a real file handle. Close it, or you leak one on every call.

Open this lesson in the learning hub

Key points

  • Most streams own nothing, so you never close them. A few sit on an open file or socket and must be closed.
  • Files.lines, Files.list and Files.walk keep a handle open until the stream is closed.
  • Wrap them in try-with-resources: try (Stream<String> s = Files.lines(p)) { ... }.
  • String.lines() holds nothing extra, so it needs no close. BufferedReader.lines() leaves the reader open.
  • onClose(runnable) registers a handler and close() runs every one that was registered.

Example

import java.io.*;
import java.util.stream.*;

public class Main {
    public static void main(String[] args) throws IOException {
        String doc = "alpha\nbeta\ngamma";

        // A String is already in memory, so this stream owns nothing. No close needed.
        System.out.println("in memory : " + doc.lines().filter(l -> l.length() == 4).toList());

        // A reader-backed stream sits on a resource. try-with-resources closes both.
        try (BufferedReader reader = new BufferedReader(new StringReader(doc));
             Stream<String> lines = reader.lines()) {
            System.out.println("reader    : " + lines.map(String::toUpperCase).toList());
        }
        System.out.println("reader    : closed, even if the body had thrown");

        // onClose registers handlers; close() runs every one of them.
        try (Stream<String> s = Stream.of("a", "b")
                .onClose(() -> System.out.println("onClose   : handler 1"))
                .onClose(() -> System.out.println("onClose   : handler 2"))) {
            System.out.println("count     : " + s.count());
        }

        // Files.lines(path) is the real case, and the shape is exactly the same.
        System.out.println("rule      : if it touches the filesystem, close it");
    }
}

If the stream came from the filesystem, it belongs in a try-with-resources.

This is a reading copy. The full lesson — with the visual explainer, the interactive lab and a Run button for the code — lives in the Streams course, and every lesson in it is listed on the Streams contents page.