如何在Java中快速搜索大型文件中的String?

时间:2016-04-28 14:10:03

标签: java io java.util.scanner

我正在尝试使用以下内容搜索特定字符串的大文本文件(400MB):

File file = new File("fileName.txt");
try {
    int count = 0;
    Scanner scanner = new Scanner(file);
    while(scanner.hasNextLine()) {
        if(scanner.nextLine().contains("particularString")) {
            count++;
            System.out.println("Number of instances of String: " + count);
        }
    }
} catch (FileNotFoundException e){
    System.out.println(e);
}

这适用于小文件,但对于此特定文件和其他大文件,它需要太长时间(> 10分钟)。

最快,最有效的方法是什么?

我现在已更改为以下内容,并在几秒钟内完成 -

try {
        int count = 0;
        FileReader fileIn = new FileReader(file);
        BufferedReader reader = new BufferedReader(fileIn);
        String line;
        while((line = reader.readLine()) != null) {
            if((line.contains("particularString"))) {
                count++;
                System.out.println("Number of instances of String " + count);
            }
        }
    }catch (IOException e){
        System.out.println(e);
    }

3 个答案:

答案 0 :(得分:7)

首先弄清楚实际读取整个文件的内容与扫描模式所花费的时间需要多长时间。

如果您的结果由读取时间占主导地位(并且假设您正确阅读,那么频道或至少是缓冲的读者)那里没什么可做的。

如果它占据主导权的扫描时间可以读取所有行,然后将要搜索的小批量行发送到工作队列,在那里你可以让多个线程拾取行批量并在其中搜索。

球场数据

  • 假设硬盘读取速度为50 MB /秒(按现代标准来说速度慢),您应该能够在<10秒内将整个文件读入内存。
  • 查看MD5散列速度基准测试(示例here)向我们展示了散列速率至少与磁盘读取速度一样快(通常更快)。此外,字符串搜索比哈希更快,更简单,并行化更好。

鉴于这2个估计值,我认为正确的实现可以轻松让您获得大约10秒的运行时间(如果您在读取行批次时开始搜索作业),并且主要由您的磁盘读取时间决定。

答案 1 :(得分:0)

扫描仪在这种情况下根本没用。在引擎盖下,它可以进行各种输入解析,检查,缓存等等。如果您的案例只是“遍历文件的所有行”,请使用基于简单BufferedReader的内容。

在您的特定情况下,我建议使用Files.lines。

示例:

  long count = Files.lines(Paths.get("testfile.txt"))
     .filter(s -> s.contains("particularString"))
     .count();
  System.out.println(count);

(请注意,流式api的这种特殊情况可能并未涵盖您实际尝试实现的内容 - 遗憾的是,您的问题并不表明该方法的结果应该是什么。)

在我的系统上,我使用Files.lines()或缓冲读取器获得大约15%的Scanner运行时。

答案 2 :(得分:-1)

使用Scanner对象中的方法 - FindWithinHorizo​​n。扫描仪将在内部创建一个FileChannel来读取文件。对于模式匹配,它最终将使用Boyer-Moore算法进行有效的字符串搜索。