Подтвердить что ты не робот

Как я могу получить количество строк в файле эффективным способом?

У меня большой файл. Он включает приблизительно 3.000-20.000 линий. Как я могу получить общее количество строк в файле с помощью Java?

4b9b3361

Ответ 1

BufferedReader reader = new BufferedReader(new FileReader("file.txt"));
int lines = 0;
while (reader.readLine() != null) lines++;
reader.close();

Обновление: Чтобы ответить на вопрос о производительности, поднятый здесь, я сделал измерение. Первое: 20 000 строк слишком мало, чтобы программа работала в течение заметного времени. Я создал текстовый файл с 5 миллионами строк. Это решение (начатое с java без параметров, таких как -server или -XX-options), потребовалось около 11 секунд на моем ящике. То же самое с wc -l (командной строки UNIX для подсчета строк), 11 секунд. Решение, читающее каждый отдельный символ и ищущее "\n", должно было быть 104 секунды, в 9-10 раз больше.

Ответ 2

использовать LineNumberReader

что-то вроде

public static int countLines(File aFile) throws IOException {
    LineNumberReader reader = null;
    try {
        reader = new LineNumberReader(new FileReader(aFile));
        while ((reader.readLine()) != null);
        return reader.getLineNumber();
    } catch (Exception ex) {
        return -1;
    } finally { 
        if(reader != null) 
            reader.close();
    }
}

Ответ 3

Я нашел какое-то решение для этого, это может быть полезно для вас

Ниже приведен фрагмент кода для, подсчитайте количество строк из файла.

  File file = new File("/mnt/sdcard/abc.txt");
  LineNumberReader lineNumberReader = new LineNumberReader(new FileReader(file));
  lineNumberReader.skip(Long.MAX_VALUE);
  int lines = lineNumberReader.getLineNumber();
  lineNumberReader.close();

Ответ 4

Java 8 + имеет очень хороший и короткий способ использования NIO:

Path path = Paths.get("./big_file.txt");
long lineCount = Files.lines(path).count();

Ответ 5

Прочитайте файл и подсчитайте количество символов новой строки. Простым способом чтения файла на Java по одной строке является класс java.util.Scanner.

Ответ 6

Это примерно так же эффективно, как и может, буферизованное двоичное чтение, без преобразования строк,

FileInputStream stream = new FileInputStream("/tmp/test.txt");
byte[] buffer = new byte[8192];
int count = 0;
int n;
while ((n = stream.read(buffer)) > 0) {
    for (int i = 0; i < n; i++) {
        if (buffer[i] == '\n') count++;
    }
}
stream.close();
System.out.println("Number of lines: " + count);

Ответ 7

Вам нужно точное количество строк или только его приближение? Я, случается, обрабатываю большие файлы параллельно, и часто мне не нужно знать точное количество строк - я затем возвращаюсь к выборке. Разделите файл на десять блоков 1MB и подсчитайте строки в каждом фрагменте, затем умножьте его на 10, и вы получите довольно хорошую аппроксимацию количества строк.

Ответ 8

Все предыдущие ответы предлагают прочитать весь файл и подсчитать количество новых строк, которые вы найдете при этом. Вы прокомментировали некоторые из них как "неэффективные", но это единственный способ сделать это. "Строка" - это не что иное, как простой символ внутри файла. И для подсчета этого символа вы должны взглянуть на каждый символ в файле.

Извините, но у вас нет выбора.: -)

Ответ 9

Если уже опубликованные ответы не достаточно быстры, вам, вероятно, придется искать решение, специфичное для вашей конкретной проблемы.

Например, если эти текстовые файлы являются журналами, которые добавляются только, и вам регулярно нужно знать количество строк в них, вы можете создать индекс. Этот индекс будет содержать количество строк в файле, когда файл был последним изменен и насколько большой был файл. Это позволит вам пересчитать количество строк в файле, пропустив все строки, которые вы уже видели, и просто прочитайте новые строки.

Ответ 10

Быстрый и грязный, но он выполняет следующие действия:

import java.io.*;

public class Counter {

    public final static void main(String[] args) throws IOException {
        if (args.length > 0) {
            File file = new File(args[0]);
            System.out.println(countLines(file));
        }
    }

    public final static int countLines(File file) throws IOException {
        ProcessBuilder builder = new ProcessBuilder("wc", "-l", file.getAbsolutePath());
        Process process = builder.start();
        InputStream in = process.getInputStream();
        LineNumberReader reader = new LineNumberReader(new InputStreamReader(in));
        String line = reader.readLine();
        if (line != null) {
            return Integer.parseInt(line.trim().split(" ")[0]);
        } else {
            return -1;
        }
    }

}

Ответ 11

Это решение примерно на 3,6 раза быстрее, чем самый высокий рейтинг при тестировании в файле с 13,8 миллионами строк. Он просто считывает байты в буфер и подсчитывает символы \n. Вы могли бы играть с размером буфера, но на моей машине ничего выше 8 КБ не делало код быстрее.

private int countLines(File file) throws IOException {
    int lines = 0;

    FileInputStream fis = new FileInputStream(file);
    byte[] buffer = new byte[BUFFER_SIZE]; // BUFFER_SIZE = 8 * 1024
    int read;

    while ((read = fis.read(buffer)) != -1) {
        for (int i = 0; i < read; i++) {
            if (buffer[i] == '\n') lines++;
        }
    }

    fis.close();

    return lines;
}

Ответ 12

Попробуйте выполнить команду unix "wc". Я не имею в виду использовать его, я имею в виду загрузить источник и посмотреть, как они это делают. Вероятно, в c, но вы можете легко переносить поведение в java. Проблема с созданием собственного заключается в том, чтобы учесть проблему завершения cr/lf.

Ответ 13

Старый пост, но у меня есть решение, которое может быть полезно для следующих людей. Почему бы просто не использовать длину файла, чтобы узнать, что такое прогрессия? Конечно, строки должны быть почти одного размера, но для больших файлов это очень хорошо:

public static void main(String[] args) throws IOException {
    File file = new File("yourfilehere");
    double fileSize = file.length();
    System.out.println("=======> File size = " + fileSize);
    InputStream inputStream = new FileInputStream(file);
    InputStreamReader inputStreamReader = new InputStreamReader(inputStream, "iso-8859-1");
    BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
    int totalRead = 0;
    try {
        while (bufferedReader.ready()) {
            String line = bufferedReader.readLine();
            // LINE PROCESSING HERE
            totalRead += line.length() + 1; // we add +1 byte for the newline char.
            System.out.println("Progress ===> " + ((totalRead / fileSize) * 100) + " %");
        }
    } finally {
        bufferedReader.close();
    }
}

Он позволяет видеть прогрессию, не делая полного чтения в файле. Я знаю, что это зависит от множества элементов, но я надеюсь, что это будет полезно:).

[издание] Вот версия с расчетным временем. Я добавил SYSO, чтобы показать прогресс и оценку. Я вижу, что у вас хорошие ошибки оценки времени после того, как вы достаточно обработали линию (я стараюсь с 10-метровыми линиями, а после 1% лечения оценка времени была достоверной на уровне 95%). Я знаю, некоторые значения должны быть установлены в переменной. Этот код быстро написан, но он полезен для меня. Надеюсь, это будет и для вас:).

long startProcessLine = System.currentTimeMillis();
    int totalRead = 0;
    long progressTime = 0;
    double percent = 0;
    int i = 0;
    int j = 0;
    int fullEstimation = 0;
    try {
        while (bufferedReader.ready()) {
            String line = bufferedReader.readLine();
            totalRead += line.length() + 1;
            progressTime = System.currentTimeMillis() - startProcessLine;
            percent = (double) totalRead / fileSize * 100;
            if ((percent > 1) && i % 10000 == 0) {
                int estimation = (int) ((progressTime / percent) * (100 - percent));
                fullEstimation += progressTime + estimation;
                j++;
                System.out.print("Progress ===> " + percent + " %");
                System.out.print(" - current progress : " + (progressTime) + " milliseconds");
                System.out.print(" - Will be finished in ===> " + estimation + " milliseconds");
                System.out.println(" - estimated full time => " + (progressTime + estimation));
            }
            i++;
        }
    } finally {
        bufferedReader.close();
    }
    System.out.println("Ended in " + (progressTime) + " seconds");
    System.out.println("Estimative average ===> " + (fullEstimation / j));
    System.out.println("Difference: " + ((((double) 100 / (double) progressTime)) * (progressTime - (fullEstimation / j))) + "%");

Не стесняйтесь улучшать этот код, если считаете это хорошим решением.

Ответ 14

Прочитайте файл по строкам и увеличьте счетчик для каждой строки, пока не прочитаете весь файл.

Ответ 15

В моих тестах другие ответы берут ~ 150-300 мс в файле строки 118,5 тыс. строк. Следующее занимает 1 мс, но только приблизительное (выводит 117 тыс. Строк) и зависит от того, что каждая строка имеет одинаковый размер.

private static void countSize(File file) {
  long fileLength = file.length();
  BufferedReader reader = null;
  try {
    reader = new BufferedReader(new FileReader(file));
    //Skip header as it is of different size
    reader.readLine();
    String text = reader.readLine();
    int lineLength = text.length();
    long lines = fileLength / lineLength;
    System.out.println(lines);
  } catch(IOException e) {
    e.printStackTrace();
  } finally {
    if(reader != null) {
      try {
        reader.close();
      } catch(IOException e) {
        //no-op
      }
    }
  }
}

Ответ 16

Возможно, самым быстрым решением в чистой Java было бы чтение файла в виде байтов с использованием канала NIO в большой ByteBuffer. Затем, используя ваши знания схемы кодирования файла, подсчитайте закодированные CR и/или NL байты в соответствии с соответствующим соглашением разделителя строк.

Ключом к максимальной пропускной способности будет:

  • убедитесь, что вы читаете файл в больших кусках,
  • избегать копирования байтов из одного буфера в другой,
  • избегать копирования/преобразования байтов в символы и
  • избегать выделения объектов для представления строк файла.

Фактический код слишком сложный для меня, чтобы писать "на лету". Кроме того, OP не требует самого быстрого решения.

Ответ 17

Буферизованный читатель переполняется

Reader r = new FileReader("f.txt");

int count = 0;
int nextchar = 0;
while (nextchar != -1){
        nextchar = r.read();
        if (nextchar == Character.getNumericValue('\n') ){
            count++;
        }
    }

Мой поиск простого примера создал тот, который действительно довольно беден. вызов read() повторяется для одного символа менее оптимальным. см. здесь для примеров и измерений.