什么';It’在Java中,最快的方法是在一个大文件中以字符串开始计算行数

什么';It’在Java中,最快的方法是在一个大文件中以字符串开始计算行数,java,performance,file,file-io,Java,Performance,File,File Io,我有巨大的文件(每个文件4.5GB),需要计算每个文件中以给定令牌开头的行数。每个文件最多可出现200000次令牌 实现如此庞大的文件遍历和字符串检测的最快方法是什么?使用扫描器和String.startsWith()是否有比以下实现更有效的方法 注: 到目前为止,扫描器似乎是瓶颈(即,如果我添加了比令牌检测更复杂的处理,并将其应用于所有行,则总体执行时间大致相同。) 我正在使用SSD,因此在硬件方面没有改进的余地 提前感谢您的帮助。一些提示(假设行相对较短,数据实际上是ASCII或类似的)

我有巨大的文件(每个文件4.5GB),需要计算每个文件中以给定令牌开头的行数。每个文件最多可出现200000次令牌

实现如此庞大的文件遍历和字符串检测的最快方法是什么?使用
扫描器
String.startsWith()
是否有比以下实现更有效的方法

注:

  • 到目前为止,
    扫描器
    似乎是瓶颈(即,如果我添加了比令牌检测更复杂的处理,并将其应用于所有行,则总体执行时间大致相同。)
  • 我正在使用SSD,因此在硬件方面没有改进的余地
提前感谢您的帮助。

一些提示(假设行相对较短,数据实际上是ASCII或类似的):

  • 一次读取一个巨大的字节缓冲区(比如说1/4GB),然后切掉不完整的行以进行下一次读取

  • 搜索字节,不要浪费时间转换为字符

  • 指示“以'\n'开始搜索模式,以行开头”,特别对待第一行

  • 使用以牺牲预处理为代价减少搜索时间的高速搜索(google表示“快速子字符串搜索”)

  • 如果需要实际的行号(而不是行号),则在单独的阶段中计算行号


我们可以将问题简化为在ByTestStream中搜索
\n
。在这种情况下,一种快速的方法是按顺序从磁盘读取数据块(大小根据经验确定,但良好的起点是1024页),然后将该数据交给另一个线程进行处理。

常见!它不是重复的,你读过你所指的问题吗?我说的是有数百万行而不是20k的文件,我还说的是令牌检测。你是“重复的”“标记仅表明您没有阅读我的问题,也没有阅读您所指的问题。现在问题已结束,我无法将其作为答案发布,但请查看
grep
。它避免了使用的读取每个字节。我也不认为这是重复的。如何取消标记?请阅读以下内容:。如果你想,你可以用ByteBuffer读取大块数据。allocateDirect将节省从文件读取的时间,你可以对分配数据的所有过程进行搜索,以标记和换行符
grep | wc-l
?这就是我最后要做的。作为参考,使用100MB缓冲区和Boyer-Moore搜索算法时,总执行时间从16分钟降至1分钟。目前,这是一个近似值,因为我仍然需要检测被一分为二的令牌,但是即使在最坏的情况下,我也会错过不到0.025%的我正在寻找的事件。。。现在已经足够精确了。谢谢小心跨越块边界的
\n
序列。
public static int countOccurences(File inputFile, String token) throws FileNotFoundException {
    int counter = 0;
    try (Scanner scanner = new Scanner(inputFile)) {
        while (scanner.hasNextLine()) {
            if (scanner.nextLine().startsWith(token)) {
                counter++;
            }
        }
    }
    return counter;
}