在Java中逐行读取文本文件的最快方法

问题描述:

对于日志处理,我的应用程序需要逐行读取文本文件。 首先,我使用了BufferedReader函数readLine(),但是我在网上读到BufferedReader在读取文件时速度很慢。
后来我尝试了与FileChannel和MappedByteBuffer一起使用的FileInputStream但在这种情况下,有没有类似的readLine(功能),所以我搜索我的文字的断行,并对其进行处理:在Java中逐行读取文本文件的最快方法

try { 
     FileInputStream f = new FileInputStream(file); 
     FileChannel ch = f.getChannel(); 
     MappedByteBuffer mb = ch.map(FileChannel.MapMode.READ_ONLY, 0L, ch.size()); 
     byte[] bytes = new byte[1024]; 
     int i = 0; 
     while (mb.hasRemaining()) { 
      byte get = mb.get(); 
      if(get == '\n') { 
       if(ra.run(new String(bytes))) 
        cnt++; 
       for(int j = 0; j<=i; j++) 
        bytes[j] = 0; 
       i = 0; 
      } 
      else 
       bytes[i++] = get; 
     } 
    } catch(Exception ex) { 
     ex.printStackTrace(); 
    } 

我知道这可能不是实现它的好方法,但是当我以字节读取文本文件时,使用BufferedReader的速度比使用BufferedReader快3倍,但调用new String(bytes)会创建一个新的String,并且在使用BufferedReader时使程序更慢。
所以我想问一下按行读取文本文件的最快方法是什么?有人说BufferedReader是解决这个问题的唯一方法。

P.S .: ra是来自dk.brics.Automaton库的RunAutomaton的一个实例。

+1

是BufferedReader真的太慢了​​吗?如果您必须使用Java编码,那么它可能是最干净,最易维护的解决方案之一。 – 2011-04-27 06:45:17

+0

如果'BufferedReader'对于您的应用程序来说真的太慢了​​,您应该考虑不要使用java或其他托管语言...... _(但我怀疑是这种情况)_ – ordag 2011-04-27 12:28:13

+1

[亚伦](http:// *。 com/users/460201/aaron)的答案即将被删除,因此我将其作为评论放在这里:“检查[此链接](http://nadeausoftware.com/articles/) 2008/02/java_tip_how_read_files_quickly)out。它包含了各种方法的速度比较。“ – 2014-07-14 09:29:44

我非常怀疑BufferedReader会造成重大的开销。添加你自己的代码可能至少是效率低下的,很可能也是错误的。

例如,在您给出的代码中,您打电话给new String(bytes),它总是要从1024字节创建一个字符串,使用平台默认编码...不是一个好主意。当然,之后你会清除数组,但是你的字符串仍然会包含一串'\ 0'字符 - 这意味着除了其他任何东西之外,还有很多浪费的空间。你应该至少限制正在创建字符串的字节数组部分(这也意味着你不需要清除数组)。

你实际上试过使用BufferedReader,发现它太慢?你通常应该编写最简单的代码,它将首先满足你的目标,然后检查它是否足够快,特别是如果你不这样做的唯一原因是你“在互联网上阅读”的未指定资源。你想让我找到数以百计的人发表不正确的表演建议的例子吗? :)

作为一种替代方案,您可能需要查看GuavaFiles.readLines()的超载,它需要LineProcessor

+1

我已经尝试过BufferedReader,它表现良好,但程序的要求是非常快,所以我只是试图找出哪个解决方案是我的最佳实施方案。 – Yoni 2011-04-27 06:57:49

+2

@Yoni:“非常快”是一个相当模糊的要求。你甚至有任何证据证明它是'BufferedReader',它是物理磁盘速度的瓶颈,而不是(很有可能)? – 2011-04-27 06:59:14

+0

如果我以字节读取相同的文件,那么使用'BufferedReader'时会快3倍。我的硬盘速度约为150mb/s,而我的程序读数为30mb/s。 – Yoni 2011-04-27 07:07:38

根据this SO贴子,您可能还想给Scanner课程一个镜头。

Using plain BufferedReader I got 100+ MB/s。从磁盘读取数据的速度很可能是你的瓶颈,所以你如何做阅读不会有太大的区别。

BufferedReader不是唯一的解决方案,但它对于99%的用例足够快,那么为什么要使事情比他们需要的更复杂呢?

框架是一种替代方案吗?

我不知道性能,但

http://commons.apache.org/io/

http://commons.apache.org/io/api-release/index.html见IOUtils类

定义非常容易使用助手类这样的情况。

我有一个非常简单的循环,它使用BufferedReader从sdcard上的一个文件读取大约2000行(50k字节),它在galaxy选项卡2上以调试模式在100mS左右读取它们。不是太糟糕。然后我把扫描仪的循环和时间通过屋顶(几十秒)去了,再加上很多GC_CONCURANT消息

Scanner scanner = new Scanner(line); 
int eventType = scanner.nextInt(16); 

因此至少在我的情况下,它是那样的问题,扫描仪,我想我需要以另一种方式扫描整数,但我不知道为什么它可能会如此缓慢