Я использую огромные файлы данных, иногда мне нужно знать только количество строк в этих файлах, обычно я открываю их и читаю построчно, пока не дойду до конца файла
Мне было интересно, есть ли более разумный способ сделать это
Переведено автоматически
Ответ 1
Это самая быстрая версия, которую я нашел на данный момент, примерно в 6 раз быстрее, чем readLines . В файле журнала размером 150 МБ это занимает 0,35 секунды по сравнению с 2,40 секундами при использовании readLines(). Просто ради интереса, команда wc -l в Linux занимает 0,15 секунды.
РЕДАКТИРОВАТЬ, 9 1/2 лет спустя: у меня практически нет опыта работы с Java, но в любом случае я попытался сравнить этот код с LineNumberReader решением ниже, поскольку меня беспокоило, что этого никто не делал. Кажется, что мое решение работает быстрее, особенно для больших файлов. Хотя, кажется, требуется несколько запусков, пока оптимизатор не выполнит достойную работу. Я немного поиграл с кодом и создал новую версию, которая неизменно работает быстрее:
intreadChars= is.read(c); if (readChars == -1) { // bail out if nothing to read return0; }
// make it easy for the optimizer to tune this loop intcount=0; while (readChars == 1024) { for (int i=0; i<1024;) { if (c[i++] == '\n') { ++count; } } readChars = is.read(c); }
// count remaining characters while (readChars != -1) { for (int i=0; i<readChars; ++i) { if (c[i] == '\n') { ++count; } } readChars = is.read(c); }
Результаты теста для текстового файла объемом 1,3 ГБ по оси y в секундах. Я выполнил 100 запусков с одним и тем же файлом и измерял каждый запуск с помощью System.nanoTime(). Вы можете видеть, что countLinesOld имеет несколько отклонений, а countLinesNew не имеет ни одного, и хотя это лишь немного быстрее, разница статистически значима. LineNumberReader явно медленнее.
Ответ 2
Я реализовал другое решение проблемы, я нашел его более эффективным при подсчете строк:
try ( FileReaderinput=newFileReader("input.txt"); LineNumberReadercount=newLineNumberReader(input); ) { while (count.skip(Long.MAX_VALUE) > 0) { // Loop just in case the file is > Long.MAX_VALUE or skip() decides to not read the entire file }
result = count.getLineNumber() + 1; // +1 because line index starts at 0 }
Ответ 3
Принятый ответ содержит ошибку off by one для многострочных файлов, которые не заканчиваются символом новой строки. Однострочный файл, заканчивающийся без перевода строки, вернет 1, но двухстрочный файл, заканчивающийся без перевода строки, тоже вернет 1. Вот реализация принятого решения, которое исправляет это. Проверки endsWithoutNewLine являются расточительными для всего, кроме окончательного чтения, но должны быть тривиальными по времени по сравнению с общей функцией.