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倍的东西。我能做什么
# 1 楼答案
您可能需要构造并检查一个巨大的正则表达式(即
Pattern.compile("word1|word2|word3|...")
)的性能,因为它构建了一个FSA,它的性能应该比简单的方法要好得多类似问题:
What's the most efficient way to find one of several substrings in Python?
# 2 楼答案
如果还没有,可以引入一些快捷方式
如果一个文件需要匹配所有模式,只要它与模式不匹配,就可以返回
false
。将最有可能失败的模式置于顶部(另一方面,如果文件需要匹配任何模式,您可以在第一个模式匹配时立即返回
true
。在这种情况下,请将最有可能匹配的模式置于顶部。)如果希望all文件匹配all模式,请确保首先加载最小的文件。这样,您就可以首先处理最容易比较的内容。您也可以尝试加载它们,以便首先处理最有可能失败的部分,但是(对我来说)对于文件和模式来说,这似乎更难做到
另外,确保只加载一次模式
# 3 楼答案
在这130k个文件上创建搜索索引可能是最可持续的方法
这里回答了一个类似的问题:Searching for matches in 3 million text files
Java环境中通常使用的库/工具:
# 4 楼答案
如果你只是比较文字,一个可能的优化可能是提前索引130000个文件。最简单的情况是(伪代码):
当前解决方案的问题是使用数组,这会导致数据库术语中的完整表扫描(实际上是集合,或者像Apache Lucene这样的更抽象的解决方案)
# 5 楼答案
在for循环中有一个100000倍的因子,在这里您可以按顺序应用每个模式
您需要找到一种方法,将100K个独立的模式组合成一个可以有效处理的模式。“.contains”查找特定文本字符串;你也可以通过正则表达式匹配来实现。使用正则表达式匹配器,您可以将单个正则表达式模式组合成一个大的正则表达式模式,预编译并应用该模式。(参见Java正则表达式文档http://docs.oracle.com/javase/tutorial/essential/regex/)
这就留下了确定哪个模式被击中的问题,如果你在意的话。如果您检查FLEX之类的词法分析工具,它们会提供一个答案。你给他们一组正则表达式,他们会生成一个快速匹配器,它会告诉你哪个模式成功