Files.readAllLines: примеры (JAVA)

Обзор применения Files.readAllLines в Java
Раздел: Файловая система
Files.readAllLines(Path path): List

Описание и сигнатуры

Метод Files.readAllLines(Path) и его перегрузка Files.readAllLines(Path, Charset) из пакета java.nio.file предоставляет удобный способ прочитать весь текстовый файл в список строк. В результате возвращается java.util.List<String>, в котором каждая запись соответствует одной строке исходного файла. Разделители строк удаляются при чтении.

Типичные сигнатуры:

  • static List<String> readAllLines(Path path) throws IOException - использует кодировку по умолчанию (Charset.defaultCharset()).
  • static List<String> readAllLines(Path path, Charset cs) throws IOException - явное указание кодировки.

Возвращаемое значение: список строк, содержащих содержимое файла без символов конца строки. Возвращаемый список реализуется обычно как изменяемый ArrayList, что позволяет далее изменять элементы или добавлять новые.

Исключения и ошибки: при проблемах ввода/вывода бросается IOException (например, NoSuchFileException, AccessDeniedException). В случае очень больших файлов возможен OutOfMemoryError, так как весь файл загружается в память. Может возникнуть SecurityException при ограниченном доступе.

Особенности поведения: метод закрывает файл после чтения. Разделители строк (\n, \r\n, \r) удаляются, характеристики кодировки существенно влияют на корректное чтение, поэтому для контроля кодировки предпочтительна перегрузка с Charset.

Короткие примеры использования

Пример 1. Простое чтение файла с использованием кодировки по умолчанию.

import java.nio.file.*;
import java.io.IOException;
import java.util.List;

Path path = Paths.get("example.txt");
try {
    List lines = Files.readAllLines(path);
    System.out.println(lines);
} catch (IOException e) {
    e.printStackTrace();
}
["Первая строка", "Вторая строка", "Третья строка"]

Пример 2. Чтение с явной кодировкой UTF-8.

import java.nio.charset.StandardCharsets;

List lines = Files.readAllLines(path, StandardCharsets.UTF_8);
System.out.println(lines.get(0));
Первая строка

Пример 3. Чтение пустого файла возвращает пустой список.

List lines = Files.readAllLines(Paths.get("empty.txt"));
System.out.println(lines.size());
0

Пример 4. Поведение при отсутствии файла (короткий пример обработки исключения).

try {
    Files.readAllLines(Paths.get("no_such.txt"));
} catch (IOException e) {
    System.out.println(e.getClass().getSimpleName() + ": " + e.getMessage());
}
NoSuchFileException: no_such.txt

Похожие API в Java и выбор в пользу них

  • Files.lines(Path) - возвращает Stream<String> и читает построчно. Предпочтителен для больших файлов или ленивой обработки, позволяет использовать параллельные операции и экономит память.
  • Files.readString(Path) (с Java 11) - возвращает весь файл как одну строку. Удобен при необходимости получить единый текст, но требует дополнительного разбиения на строки.
  • Files.newBufferedReader(Path, Charset) вместе с BufferedReader.readLine() - даёт контроль над чтением, полезно для потоковой обработки и при необходимости обработки больших файлов без загрузки в память.
  • Files.readAllBytes(Path) - возвращает байтовый массив, полезен для бинарных файлов или когда требуется собственная декодировка.

Выбор между ними зависит от размера файла, требований к памяти, желаемой кодировки и необходимости потоковой обработки.

Аналоги в других языках и отличия

Краткий обзор по языкам с примерами.

  • Python
    # pathlib
    from pathlib import Path
    lines = Path('example.txt').read_text(encoding='utf-8').splitlines()
    print(lines)
    ['Первая строка', 'Вторая строка', 'Третья строка']
    Отличие: читается весь текст, затем splitlines удаляет разделители. Есть также Path.read_text и open().readlines().
  • JavaScript (Node.js)
    const fs = require('fs');
    const data = fs.readFileSync('example.txt', 'utf8').split(/\r?\n/);
    console.log(data);
    [ 'Первая строка', 'Вторая строка', 'Третья строка' ]
    Отличие: синхронное чтение блокирует поток; для больших файлов используется createReadStream.
  • PHP
    $lines = file('example.txt', FILE_IGNORE_NEW_LINES);
    print_r($lines);
    Array ( [0] => Первая строка [1] => Вторая строка )
    Отличие: функция file возвращает массив строк, можно указать флаг для удаления символов конца строки.
  • C#
    var lines = System.IO.File.ReadAllLines("example.txt");
    Console.WriteLine(lines[0]);
    Первая строка
    Отличие: API очень похож, есть File.ReadLines для ленивой обработки.
  • Go
    data, _ := os.ReadFile("example.txt")
    lines := strings.Split(strings.ReplaceAll(string(data), "\r\n", "\n"), "\n")
    fmt.Println(lines)
    [Первая строка Вторая строка Третья строка]
    Отличие: читается байтовый слайс, затем декодируется в строку и разбивается.
  • Kotlin
    val lines = java.nio.file.Files.readAllLines(Paths.get("example.txt"), Charsets.UTF_8)
    println(lines)
    [Первая строка, Вторая строка]
    Отличие: использует те же java.nio интерфейсы, есть kotlin.io.File.readLines удобная обёртка.
  • Lua
    local t = {}
    for line in io.lines('example.txt') do table.insert(t, line) end
    for i,v in ipairs(t) do print(v) end
    Первая строка
    Вторая строка
    Отличие: построчное чтение через итератор; не загружает весь файл в одну структуру по умолчанию.

Основная разница между Java и большинством языков - необходимость явно указать кодировку или учесть системную по умолчанию и нагрузка на память при чтении целиком.

Типичные ошибки и примеры

Ошибка 1. Файл не найден - NoSuchFileException.

try {
    Files.readAllLines(Paths.get("missing.txt"));
} catch (IOException e) {
    System.out.println(e.getClass().getSimpleName());
}
NoSuchFileException

Ошибка 2. Проблемы доступа - AccessDeniedException или SecurityException.

// при попытке читать файл без прав
try {
    Files.readAllLines(Paths.get("/root/secret.txt"));
} catch (IOException e) {
    System.out.println(e.getClass().getSimpleName());
}
AccessDeniedException

Ошибка 3. Переполнение памяти при очень большом файле.

// гипотетический пример большого файла
List lines = Files.readAllLines(Paths.get("huge.txt"));
// может привести к OutOfMemoryError при недостатке памяти
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space

Ошибка 4. Неправильная кодировка приводит к искажениям символов.

List lines = Files.readAllLines(path, StandardCharsets.ISO_8859_1);
// если файл в UTF-8, появятся некорректные символы
Пекап

Изменения и эволюция API

Метод Files.readAllLines введён в Java 7 вместе с NIO.2. С выходом Java 11 появились новые удобные методы: Files.readString и Files.writeString для чтения/записи текста как одной строки с использованием UTF-8 по умолчанию в их сигнатурах без явной кодировки. Поведение readAllLines в отношении удаления разделителей строк и возвращаемого списка осталось стабильным; изменений в семантике не отмечено.

Расширенные и редкие сценарии применения

Пример 1. Чтение файла в zip-архиве через FileSystem (чтение как обычного файла).

Пример java
import java.nio.file.*;
import java.util.*;
import java.io.IOException;

Map env = new HashMap<>();
env.put("create", "false");
try (FileSystem fs = FileSystems.newFileSystem(Paths.get("archive.zip"), null)) {
    Path p = fs.getPath("docs/example.txt");
    List lines = Files.readAllLines(p, StandardCharsets.UTF_8);
    System.out.println(lines.size());
}
3

Пример 2. Преобразование результата в поток для дальнейшей обработки без повторного чтения файла.

Пример java
List lines = Files.readAllLines(path, StandardCharsets.UTF_8);
long nonEmpty = lines.stream()
    .map(String::trim)
    .filter(s -> !s.isEmpty())
    .count();
System.out.println(nonEmpty);
2

Пример 3. Создание неизменяемого представления и кэширование содержимого.

Пример java
List cached = Collections.unmodifiableList(Files.readAllLines(path, StandardCharsets.UTF_8));
// cached нельзя изменить, можно безопасно передать в другие модули
[Первая строка, Вторая строка]

Пример 4. Обработка больших файлов с контролем памяти: сравнение с Files.lines.

Пример java
// Небезопасно для больших файлов
try {
    List all = Files.readAllLines(bigPath);
} catch (OutOfMemoryError e) {
    System.out.println("Недостаточно памяти для чтения целиком");
}

// Рекомендация: использовать поток
try (Stream stream = Files.lines(bigPath)) {
    long count = stream.filter(l -> !l.trim().isEmpty()).count();
    System.out.println(count);
}
Недостаточно памяти для чтения целиком
123456

Пример 5. Чтение и восстановление исходных разделителей строк (если требуется): сначала прочитать байты, затем анализировать.

Пример java
byte[] data = Files.readAllBytes(path);
String text = new String(data, StandardCharsets.UTF_8);
// вручную разделить и сохранить разделители
List parts = new ArrayList<>();
Matcher m = Pattern.compile("(.*?)(\r\n|\n|\r|$)", Pattern.DOTALL).matcher(text);
while (m.find()) parts.add(m.group(1) + m.group(2));
System.out.println(parts.get(0));
Первая строка\n

Пример 6. Сочетание с parallelStream для распараллеливания постобработки (внимание к потоко-безопасности).

Пример java
List lines = Files.readAllLines(path);
Map map = lines.parallelStream()
    .map(String::length)
    .collect(Collectors.groupingByConcurrent(Integer::intValue, Collectors.counting()));
System.out.println(map);
{5=2, 12=1}

Примеры демонстрируют, как readAllLines может использоваться в разных задачах, и когда стоит предпочесть ленивый поток либо побайтовое чтение.

джава Files.readAllLines function comments

En
Files.readAllLines Читает все строки из файла