Статьи

Подсчёт количества строк в текстовом файле

23 марта 2021

Тэги: Java ввод-вывод Java 11 алгоритмы

Содержание

  1. Вариант c LineNumberReader
  2. Вариант c инкрементом

Во многих редакторах при работе с текстовым документом вы можете видеть, сколько всего строк содержится в этом файле. Строки между собой разделяются символом перевода строки, который в каждой операционной системе (Windows, Unix, Mac) свой.

Давайте разберёмся, как быстро подсчитать количество строк в текстовом файле независимо от той ОС, в котором выполняется наш код. Более того, текстовый файл может быть сколь угодно большим, поэтому мы будем использовать буферизацию потока, чтобы не израсходовать всю доступную оперативную память.

Предположим, наш метод принимает на вход абсолютный путь до целевого файла, а возвращает количество строк в виде целочисленного типа long. Рассмотрим две реализации.

Вариант c LineNumberReader

public static long getLineCountByReader(String fileName) throws IOException {
    try (var lnr = new LineNumberReader(new BufferedReader(new FileReader(fileName)))) {
        while (lnr.readLine() != null) ;
        return lnr.getLineNumber();
    }
}

Сначала мы в конструкции try-with-resources последовательно создаём три Reader'a, оборачивая один в другой:

  1. FileReader - для работы с файлом.
  2. BufferedReader - для буферизации потока и ускорения обработки.
  3. LineNumberReader - собственно, для подсчёта количества строк.

Все перечисленные ридеры являются ресурсами и конструкция try-with-resources гарантирует нам, что после выхода из этого блока они все будут закрыты.

Затем в цикле вызываем у LineNumberReader метод readLine(). Поскольку никаких дополнительных действий нам делать не надо, то тело цикла будет пустым. После выхода из цикла метод getLineNumber() возвращает нам количество строк в файле.

На мой взгляд, это наиболее «читаемая» реализация, но ниже мы рассмотрим чуть более быструю версию. А пока можем вызвать наш метод:

public static void main(String[] args) throws IOException {
    System.out.println("Lines count: " + getLineCountByReader("/home/user/very-large-file.txt"));
}

Даже для текстового файла на десятки мегабайт подсчёт количества строк занимает меньше секунды.

Вариант c инкрементом

Наш метод можно немного ускорить, отказавшись от LineNumberReader. Вместо этого будем подсчитывать строки с помощью обычного инкремента.

public static long getLineCountByIncrement(String fileName) throws IOException {
    var lines = 0L;
    try (var reader = new BufferedReader(new FileReader(fileName))) {
        while (reader.readLine() != null) {
            lines++;
        }
        return lines;
    }
}

Здесь мы точно так же в блоке try создаём FileReader и BufferedReader, чтобы по окончании они были гарантированно закрыты. После этого в цикле на каждой итерации также вызываем метод readLine(). На этот раз тело цикла у нас не пустое, в нём мы увеличиваем переменную lines на 1. Такая реализация быстрее предыдущей примерно на 10%.



Комментарии

Добавить комментарий

×

devmark.ru