Java 文件中的行数

2022-08-31 05:49:58

我使用巨大的数据文件,有时我只需要知道这些文件中的行数,通常我会打开它们并逐行读取它们,直到我到达文件的末尾

我想知道是否有更聪明的方法来做到这一点


答案 1

这是我迄今为止发现的最快的版本,比readLines快6倍。在 150MB 的日志文件上,这需要 0.35 秒,而使用 readLines() 时需要 2.40 秒。只是为了好玩,linux的wc -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年半后:我几乎没有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();
    }
}

1.3GB 文本文件的基准测试,y 轴(以秒为单位)。我使用同一文件执行了 100 次运行,并使用 .你可以看到它有一些异常值,并且没有异常值,虽然它只是快了一点,但差异在统计上是显着的。 显然较慢。System.nanoTime()countLinesOldcountLinesNewLineNumberReader

Benchmark Plot


答案 2

我已经实现了这个问题的另一个解决方案,我发现它在计算行数时更有效:

try
(
   FileReader       input = new FileReader("input.txt");
   LineNumberReader count = new LineNumberReader(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
}

推荐