Files.readAllLines()

Load a small text file as a List of lines with any line ending handled for you, ready for filtering, parsing or indexing.

Signature
public static List<String> readAllLines(Path path, Charset cs) throws IOException
  • Added in Java Java 7

Parameters

ParameterTypeDescription
$pathPathThe file to read.
$csoptionalCharset= StandardCharsets.UTF_8The charset used to decode the bytes. Leave it out to use readAllLines(Path), which decodes as UTF-8.

Return value

List<String>The lines of the file in order, without their line terminators.

Errors

IOException if the file cannot be read (NoSuchFileException when it does not exist), including MalformedInputException when the bytes are not valid in the charset.

Changelog

  • PHP Java 8Added the readAllLines(Path) overload, which decodes as UTF-8 without naming a charset.

Files.readAllLines(path) reads the whole file, splits it into lines and returns them as a List<String>. Like readString, it reads everything into memory at once, so it suits small files: an allowlist, a list of feature flags, a seed file, a short CSV.

How lines are split

A line ends at \n, \r\n or a lone \r, and the terminator is not included in the string. That means a file saved on Windows gives the same list as one saved on Linux, with no stray \r at the end of each value. A final line terminator does not create an extra empty line, but blank lines in the middle of the file do come back as empty strings.

When to use it, and when not

  • You need random access or several passes over the lines: readAllLines.
  • You need one pass over a file of unknown or large size: Files.lines or newBufferedReader, which keep memory flat.
  • You want the raw text, line breaks and all: readString.

The Javadoc does not promise whether the returned list is modifiable. The current JDK returns an ArrayList, but if you keep the list in a field, wrap it with List.copyOf so nobody depends on that.

Common mistakes

Treating every line as data. Config-style files have comments and blank lines, and lines copied from a spreadsheet often carry trailing spaces. Strip and filter before parsing. Also, the no-charset overload is UTF-8; an exported file in another encoding throws MalformedInputException rather than silently corrupting names.

List<String> origins = Files.readAllLines(Path.of("allowed-origins.txt")).stream()
        .map(String::strip)
        .filter(line -> !line.isEmpty() && !line.startsWith("#"))
        .toList();

Example

Try it yourself
Loading editor…
Press Run to execute the code.

When to use it

  • Load a list of allowed CORS origins or blocked IP addresses at startup and build a Set from it.
  • Read a small seed CSV of reference data in a migration or integration test and insert the rows.
  • Parse a short key=value file that an operator edits by hand, skipping comments and blank lines.

Frequently asked questions

What is the difference between Files.readAllLines and Files.lines?

readAllLines reads the whole file into a List immediately and closes it. Files.lines returns a lazy Stream that reads as you consume it and must be closed, so it suits large files.

Does readAllLines include the newline characters?

No. Each element is the line without its terminator, whether the file used \n, \r\n or \r.

Can I modify the list returned by readAllLines?

The specification does not say. The current JDK returns an ArrayList, but code should copy it (new ArrayList<>(lines) or List.copyOf(lines)) rather than rely on that.

More examples

Windows line endings

readAllLines treats \r\n as one terminator and drops it, so the values carry no hidden carriage return. Splitting readString output on "\n" by hand would leave \r on every line, a classic cause of failed equality checks.

Example · java
void main() throws IOException {
    Path file = Files.createTempFile("users", ".csv");
    try {
        Files.writeString(file, "id,name\r\n1,Ada\r\n2,Linus\r\n");
        List<String> lines = Files.readAllLines(file);
        IO.println(lines);
        IO.println("any line ends with CR: " + lines.stream().anyMatch(l -> l.endsWith("\r")));
        IO.println("bytes: " + Files.size(file));
    } finally {
        Files.deleteIfExists(file);
    }
}

// Output:
// [id,name, 1,Ada, 2,Linus]
// any line ends with CR: false
// bytes: 25

Parsing a CSV into records

subList(1, size) skips the header row without copying. A plain split on commas only works for simple files with no quoted fields; real CSV from spreadsheets needs a proper parser.

Example · java
record User(int id, String email) {}

void main() throws IOException {
    Path file = Files.createTempFile("seed", ".csv");
    try {
        Files.writeString(file, """
            id,email
            1,[email protected]
            2,[email protected]
            """);

        List<String> lines = Files.readAllLines(file);
        List<User> users = lines.subList(1, lines.size()).stream()
                .map(line -> line.split(","))
                .map(parts -> new User(Integer.parseInt(parts[0]), parts[1]))
                .toList();
        users.forEach(IO::println);
    } finally {
        Files.deleteIfExists(file);
    }
}

// Output:
// User[id=1, [email protected]]
// User[id=2, [email protected]]

Round trip with Files.write

Files.write(path, lines) and readAllLines are a matching pair: one adds a terminator after each line, the other removes it. The final terminator does not produce an empty fourth element.

Example · java
void main() throws IOException {
    Path file = Files.createTempFile("flags", ".txt");
    try {
        List<String> flags = List.of("new-checkout", "dark-mode", "beta-search");
        Files.write(file, flags); // adds a line separator after every line
        List<String> back = Files.readAllLines(file);
        IO.println(back);
        IO.println("same list: " + back.equals(flags));
    } finally {
        Files.deleteIfExists(file);
    }
}

// Output:
// [new-checkout, dark-mode, beta-search]
// same list: true

Discussion

  • Be the first to comment on this lesson.