Включите исполнение JavaScript в браузере, чтобы запустить приложение.
23 янв 2025

Чтение текстовых файлов в Java

Автоматическое чтение текстовых данных нередко оказывается непростой задачей при Java-разработке. Рассказываем, какие методы чтения существуют и как выбрать подходящий в зависимости от характеристик файла.

Начинающие Java-разработчики зачастую сталкиваются с трудностями при извлечении текстовой информации. Рассмотрим разные методы чтения ASCII-файлов в Java, обсудим их особенности, позволяющие сделать обоснованный выбор в конкретных ситуациях.

Как читать текстовые файлы в Java

Есть несколько механизмов чтения файлов в Java. У каждого есть свои плюсы и минусы, определяющие область его эффективного применения. Неправильный выбор метода приводит к снижению производительности, ошибкам в обработке данных или даже к неожиданным сбоям программы. Поэтому понимание различных подходов к чтению текстовых файлов является ключевым навыком для любого Java-программиста, независимо от уровня его квалификации. Опишем основные.

BufferedReader и FileReader

Самый простой и часто используемый метод чтения текста — комбинация классов FileReader/ BufferedReader. Первый инициирует поток данных для чтения, второй обеспечивает более эффективное чтение данных из этого потока, буферизирует информацию и предоставляет метод readLine() для построчного извлечения. Такой подход удобен для текстовых файлов с построчной организацией данных. Он позволяет обрабатывать информацию по частям, не загружая все содержимое файла в оперативную память одновременно.

Вот фрагмент кода, демонстрирующий типовой пример использования этого метода:

BufferedReader reader = null;

try {

  reader = new BufferedReader(new FileReader("file.txt"));

  String line;

  while ((line = reader.readLine()) != null) {

    System.out.println(line); // Обработка каждой строки

  }

} catch (IOException e) {

  System.err.println("Ошибка чтения файла: " + e.getMessage());

} finally {

  try {

    if (reader != null) {

      reader.close(); // Важно закрыть поток для освобождения ресурсов

    }

  } catch (IOException e) {

    System.err.println("Ошибка закрытия файла: " + e.getMessage());

  }

}
java

Обратите внимание на использование блока try-catch-finally. Он гарантирует закрытие потока reader, даже если в процессе чтения произошла ошибка. Это предотвращает утечку ресурсов и обеспечивает стабильность работы приложения. Вместо простого вывода строки на консоль внутри цикла while можно реализовать любую необходимую обработку прочитанных данных.

Scanner

Класс Scanner в Java предоставляет альтернативный, более гибкий подход к чтению данных из файлов. В отличие от BufferedReader, который ориентирован на построчную работу, Scanner способен анализировать входной поток и извлекать из него данные разных типов: целые числа (int, long), числа с плавающей точкой (float, double), строки. Это делает его особенно удобным для работы с файлами с разделителями (CSV, TSV) или файлами, где разные типы данных перемещаются. Но для объемных файлов он менее эффективен, чем BufferedReader, поскольку он не использует буферизацию на таком же уровне.

Приведем пример:

Scanner scanner = null;

try {

  scanner = new Scanner(new File("file.txt"));

  while (scanner.hasNextLine()) {

    String line = scanner.nextLine();

    System.out.println(line); // Обработка строки, возможно, с последующим разбором на части

  }

} catch (FileNotFoundException e) {

  System.err.println("Файл не найден: " + e.getMessage());

} finally {

  if (scanner != null) {

    scanner.close(); // Закрытие Scanner для освобождения ресурсов

  }

}
java

Аналогично примеру с BufferedReader, использование блока try-catch-finally обязательно для корректного управления ресурсами и обработки исключения FileNotFoundException, которое возникает, если указанный файл отсутствует. Внутри цикла while можно добавить более сложную логику для парсинга и обработки данных в соответствии с форматом файла. Например, можно разбить строку на части с помощью метода split() и преобразовать полученные подстроки в числа или другие типы данных с помощью методов nextInt(), nextDouble().

Files и Paths

В версиях Java от седьмой и выше читать файлы можно с помощью сочетания Files.readAllLines с Paths.get.  Этот метод считывает строки в список List<String>. Для объемных массивов данных этот подход может быть неэффективным из-за загрузки всего содержимого в память. Пример:

try {

    List<String> lines = Files.readAllLines(Paths.get("file.txt"), StandardCharsets.UTF_8);

    for (String line : lines) {

        System.out.println(line);

    }

} catch (IOException e) {

    System.err.println("Ошибка чтения файла: " + e.getMessage());

}
java

Обратите внимание на добавление StandardCharsets.UTF_8 в readAllLines.  Это важно для указания кодировки файла (здесь UTF-8). Также нужно обработать возможные исключения IOException. В блоке try после получения списка строк можно реализовать любую необходимую логику обработки данных.

Вывод

Мастерство в работе с текстовыми файлами — важное умение для Java-разработчика. Понимание разных методов и их особенностей позволяет выбирать наиболее подходящий инструмент для конкретной задачи, обеспечивая эффективность и надежность приложения.

Выбор между BufferedReader, Scanner и Files.readAllLines должен основываться на оценке размера файла, структуры данных и требуемых характеристик производительности. Files.readAllLines подходит для файлов небольшого объема, BufferedReader эффективен для больших, а Scanner гибок в обработке данных разных типов. Критически важно грамотно обрабатывать исключения и освобождать ресурсы, используя блоки try-catch-finally.