我使用巨大的数据文件,有时我只需要知道这些文件中的行数,通常我打开它们并逐行读取它们,直到到达文件末尾
我想知道是否有更聪明的方法来做到这一点
这是迄今为止我发现的最快的版本,比 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 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) {
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()
。你可以看到countLinesOld
有一些异常值,并且countLinesNew
没有,虽然它只是快一点,但差异在统计上是显着的。LineNumberReader
显然更慢。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)