Это - самая быстрая версия, которую я нашел до сих пор, приблизительно в 6 раз быстрее, чем readLines. На файле журнала 150 МБ это занимает 0,35 секунды, по сравнению с 2,40 секундами при использовании readLines (). Только для забавы, Linux' туалет-l команда занимает 0,15 секунды.
public static int countLinesOld(String filename) throws IOException {
InputStream is = new BufferedInputStream(new FileInputStream(filename));
try {
byte[] c = new byte[1024];
int count = 0;
int readChars = 0;
boolean empty = true;
while ((readChars = is.read(c)) != -1) {
empty = false;
for (int i = 0; i < readChars; ++i) {
if (c[i] == '\n') {
++count;
}
}
}
return (count == 0 && !empty) ? 1 : count;
} finally {
is.close();
}
}
РЕДАКТИРОВАНИЕ, 9 1/2 лет спустя: у Меня нет практически опыта Java, но так или иначе я попытался сравнить этого кода с LineNumberReader
решение ниже, так как это беспокоило меня, что никто не сделал это. Кажется, что специально для больших файлов мое решение быстрее. Хотя это, кажется, берет несколько выполнений, пока оптимизатор не делает достойное задание. Я играл немного с кодом и произвел новую версию, которая является последовательно самой быстрой:
public static int countLinesNew(String filename) throws IOException {
InputStream is = new BufferedInputStream(new FileInputStream(filename));
try {
byte[] c = new byte[1024];
int readChars = is.read(c);
if (readChars == -1) {
// bail out if nothing to read
return 0;
}
// make it easy for the optimizer to tune this loop
int count = 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) {
System.out.println(readChars);
for (int i=0; i<readChars; ++i) {
if (c[i] == '\n') {
++count;
}
}
readChars = is.read(c);
}
return count == 0 ? 1 : count;
} finally {
is.close();
}
}
Сравнительный тест resuls для текстового файла на 1.3 ГБ, оси y в секундах. Я выполнил 100 выполнений с тем же файлом и измерил каждое выполнение с System.nanoTime()
. Вы видите, что countLinesOld
имеет несколько выбросов, и countLinesNew
не имеет ни одного и в то время как это только немного быстрее, различие является статистически значительным. LineNumberReader
ясно медленнее.
Только способ знать, сколько строк там находится в файле, состоит в том, чтобы считать их. Можно, конечно, создать метрику из данных, дающих Вам средняя длина одной строки, и затем получить размер файла и разделить это с в среднем. длина, но это не будет точно.
В Основанных на Unix системах используйте эти wc
команда на командной строке.
Если у Вас не будет индексных структур, Вы не обойдете чтение полного файла. Но можно оптимизировать его, стараясь не читать его линию за линией и использовать regex для соответствия всем разделителям строки.
Ответ с помощью метода count () выше дал мне неправильный счет строк, если файл не имел новой строки в конце файла - он не смог подсчитать последнюю строку в файле.
Этот метод мне больше подходит:
public int countLines(String filename) throws IOException {
LineNumberReader reader = new LineNumberReader(new FileReader(filename));
int cnt = 0;
String lineRead = "";
while ((lineRead = reader.readLine()) != null) {}
cnt = reader.getLineNumber();
reader.close();
return cnt;
}