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.
public static List<String> readAllLines(Path path, Charset cs) throws IOException- Added in Java Java 7
Parameters
| Parameter | Type | Description |
|---|---|---|
$path | Path | The file to read. |
$csoptional | Charset= StandardCharsets.UTF_8 | The 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.linesornewBufferedReader, 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
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.
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: 25Parsing 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.
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.
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