10 февраля 2024
Во многих редакторах при работе с текстовым документом вы можете видеть, сколько всего строк содержится в этом файле. Строки между собой разделяются символом перевода строки, который в каждой операционной системе (Windows, Unix, Mac) свой.
Давайте разберёмся, как быстро подсчитать количество строк в текстовом файле независимо от той ОС, в котором выполняется наш код. Более того, текстовый файл может быть сколь угодно большим, поэтому мы будем использовать буферизацию потока, чтобы не израсходовать всю доступную оперативную память.
Предположим, наш метод принимает на вход абсолютный путь до целевого файла, а возвращает количество строк в виде целочисленного типа long. Рассмотрим две реализации.
Сначала мы в конструкции try-with-resources последовательно создаём два Reader'a, оборачивая один в другой:
Буферизация потока здесь в явном виде не требуется, т.к. LineNumberReader уже наследуется от BufferedReader.
Все перечисленные ридеры поддерживают интерфейс AutoCloseable и конструкция try-with-resources гарантирует нам, что после выхода из этого блока они все будут закрыты.
Затем в цикле вызываем у LineNumberReader метод readLine(). Поскольку никаких дополнительных действий нам делать не надо, то тело цикла будет пустым. После выхода из цикла метод getLineNumber() возвращает нам количество строк в файле.
На мой взгляд, это наиболее «читаемая» реализация, но ниже мы рассмотрим чуть более быструю версию. А пока можем вызвать наш метод:
Даже для текстового файла на десятки мегабайт подсчёт количества строк занимает меньше секунды.
Наш метод можно немного ускорить, отказавшись от LineNumberReader. Вместо этого будем подсчитывать строки с помощью обычного инкремента.
Здесь мы точно так же в блоке try создаём FileReader и BufferedReader, чтобы по окончании они были гарантированно закрыты. После этого в цикле на каждой итерации также вызываем метод readLine(). На этот раз тело цикла у нас не пустое, в нём мы увеличиваем переменную lines на 1. Такая реализация быстрее предыдущей примерно на 10%.
Kotlin, Java, Spring, Spring Boot, Spring Data, SQL, PostgreSQL, Oracle, Linux, Hibernate, Collections, Stream API, многопоточность, файлы, Nginx, Apache, maven, gradle, JUnit, YouTube, новости, руководство, ООП, алгоритмы, головоломки, rest, GraphQL, Excel, XML, json, yaml.