有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

Java中匹配多个文件和多个模式的字符串

下面是我想做的:一方面,我有一个文本文件,其中包含大约100.000个字符串模式(每个字符串在一个新行中),其中大多数大约有40-200个字符长。另一方面,我有大约130000个文件,大小从几千字节到几百兆字节的大文件(然而,95%的文件只有几百KB)

现在,我想将130k个文件中的每个与100k个模式中的所有进行匹配

现在我正在使用。contains()方法,下面是一些示例代码:

String file = readFile(somefile.pdf); // see benchmark below
String[] patterns = readFile(patterns.txt).split("\n"); // read 100k patterns into an array
for(int i = 0; patterns.length-1; i++){
    if(file.contains(patterns[i])){
        // pattern matched 
    }else{
        // patttern not matched
    }
}

我在功能相当强大的桌面系统(4core 2.9ghz、4GB内存、SSD)上运行此功能,但性能非常差:

当某个文件出现时。pdf是一个1.2mb的文件,匹配所有100k模式需要约43秒。 400kb的内存约为14秒。50kb的文件大约需要2秒

这太慢了,我需要性能提高40-50倍的东西。我能做什么


共 (5) 个答案

  1. # 2 楼答案

    如果还没有,可以引入一些快捷方式

    如果一个文件需要匹配所有模式,只要它与模式不匹配,就可以返回false。将最有可能失败的模式置于顶部
    (另一方面,如果文件需要匹配任何模式,您可以在第一个模式匹配时立即返回true。在这种情况下,请将最有可能匹配的模式置于顶部。)

    如果希望all文件匹配all模式,请确保首先加载最小的文件。这样,您就可以首先处理最容易比较的内容。您也可以尝试加载它们,以便首先处理最有可能失败的部分,但是(对我来说)对于文件和模式来说,这似乎更难做到


    另外,确保只加载一次模式

  2. # 3 楼答案

    在这130k个文件上创建搜索索引可能是最可持续的方法

    这里回答了一个类似的问题:Searching for matches in 3 million text files

    Java环境中通常使用的库/工具:

    • 卢塞恩
    • 索尔
    • 弹性搜索
  3. # 4 楼答案

    如果你只是比较文字,一个可能的优化可能是提前索引130000个文件。最简单的情况是(伪代码):

    for file in files
      read file as string
      split string into tokens (e.g. by white-space)
      set = all tokens in a HashSet
      for every pattern in patterns
          if set.contains(pattern)
              // pattern found
          else
              // pattern not found
    

    当前解决方案的问题是使用数组,这会导致数据库术语中的完整表扫描(实际上是集合,或者像Apache Lucene这样的更抽象的解决方案)

  4. # 5 楼答案

    在for循环中有一个100000倍的因子,在这里您可以按顺序应用每个模式

    您需要找到一种方法,将100K个独立的模式组合成一个可以有效处理的模式。“.contains”查找特定文本字符串;你也可以通过正则表达式匹配来实现。使用正则表达式匹配器,您可以将单个正则表达式模式组合成一个大的正则表达式模式,预编译并应用该模式。(参见Java正则表达式文档http://docs.oracle.com/javase/tutorial/essential/regex/

    这就留下了确定哪个模式被击中的问题,如果你在意的话。如果您检查FLEX之类的词法分析工具,它们会提供一个答案。你给他们一组正则表达式,他们会生成一个快速匹配器,它会告诉你哪个模式成功