如何提高Java中读取大文件的速度?

4
我刚刚读取了一个大小为167MB,行数为1884000的文件。我使用的方法是BufferedReader按行读取文件。但我发现随着当前行号的增加,读取文件的过程变得越来越慢(在这种情况下,读完整个文件耗时3小时30分钟)。虽然我知道使用nio可以加速这个过程,但我想继续按行读取文件。
我的代码如下,请问有什么建议吗?非常感谢!
String htmlContentPath = html.getAbsolutePath();
BufferedReader reader = new  BufferedReader(new InputStreamReader(new FileInputStream(htmlContentPath)));
String line = null;
int cnt = 0;
while((line = reader.readLine()) != null)       {
    this.proc(line);
    if((cnt++ % 2000) == 0) {
        logger.info("current line number:\t"+cnt);
    }
}

2
proc(line) 是什么作用?它会随着运行时间的增长而变慢吗? - Michael Myers
每次循环都需要调用 this.proc(line) 吗? - kevmo314
  1. 使用多个线程
  2. 正确同步线程
  3. 使用Java NIO的“通道(Channels)” :)
- An SO User
2
即使我慢慢阅读,速度也达到了100MB/s http://vanillajava.blogspot.co.uk/2011/01/how-slow-can-you-readwrite-files-in.html 我怀疑的不是阅读本身而是处理文本时出现的延迟。 - Peter Lawrey
@LittleChild 多线程不会有任何作用。只有一个文件,在一个文件系统上,在一个磁盘上,而且这些东西都不支持多线程。没有理由相信 Channel 会更快。 - user207421
显示剩余3条评论
4个回答

2
你应该能在这里找到答案:

http://nadeausoftware.com/articles/2008/02/java_tip_how_read_files_quickly

为了获得最佳的Java读取性能,有四件事情需要记住:
  • 通过一次读取一个数组而不是一个字节来最小化I/O操作。 8K字节数组是一个很好的大小。

  • 通过一次获取一个数组而不是一个字节来最小化方法调用。使用数组索引来获取数组中的字节。

  • 如果您不需要线程安全,请最小化线程同步锁。要么对线程安全类进行较少的方法调用,要么使用非线程安全的类,如FileChannel和MappedByteBuffer。

  • 在JVM / OS、内部缓冲区和应用程序数组之间最小化数据复制。使用具有内存映射的FileChannel或直接或包装的数组ByteBuffer。


他正在通过BufferedReader逐行阅读,这已经满足了你的前两个要点。 - user207421

0
这可能是由于交换引起的,取决于您在proc方法中文件的内存占用情况,您可以对进程执行visualVM以查看堆状态,然后调整(xms,xmx)/减少方法的内存消耗。
干杯。

0
当我第一次阅读您的问题时,我想建议您注释掉对proc()的调用,然后使用其他答案中的一些方法加速文件的读取(因为您已经注释掉了处理调用,所以这应该是整个执行时间)。
经过进一步思考,我建议您使用分析器(没有任何行被注释)。如果您正在使用Eclipse,则Eclipse Marketplace上有几个JVM分析器,我相信其他IDE也集成了分析器。分析器可以显示代码中的热点——您看起来花费大量时间的地方。那些信息,再加上您对程序逻辑的了解,将提供加速最坏瓶颈的方法。
这是一个迭代的过程,结果越来越好。
我还建议您在测试时先使用较小的样本文件。

@Ivan。我确定。我只知道Eclipse,但是性能分析是一个关键功能,你会在任何IDE上找到它。没有针对NetBeans或IntelliJ的轻蔑意图。 - Chris Gerken

0

这对我来说听起来像是一个内存问题(由于内存不足,垃圾回收的需求增加,经常会出现减速现象)。

您发布的代码看起来不应该随着行号的增加而变慢(假设proc()调用是“干净”的)。

我赞同Chris G的建议,删除proc()调用,看看当您只读取文件而不处理任何行时是否仍然出现减速。

我还想补充一点,您可以尝试使用-Xmx和-Xms标志,在开始时为JVM提供更多的内存。

这里有一个相关的问题:Java线程在处理结束时变慢


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接