在大文本文件中搜索字符串的最快方法

为了查找相当大的文本文件中的字符串列表(最多1GB文本文件),可以实现的最快技术/算法是什么。 对于初学者来说,我正在使用C#并且能够实现逻辑(简单地通过匹配文件和字符串列表,每次都是字符串。这意味着文件将被读取n个字符串以匹配“次”)但是因为我正在处理很多文件,所以它会永远运行它们并获得匹配。即使它不是C#,我也会接受任何建议。

为了详细说明,我有一个包含许多数字的文本文件(A),我有很多大文件(B)。 我试图获取(A)中的每个元素,并逐行查看(B)中是否存在匹配。 如果匹配,我将整行写入文本文件。 我这样做的方式非常传统,单个文件需要花费大量时间,而我有数百个,大小高达1GB

感谢你的时间

执行此操作的标准方法是实现Aho-Corasick算法 。 它会一次读取文件,并查找所有出现的字符串。 有关提供实现和一些示例的文章,请参阅https://www.informit.com/guides/content.aspx?g=dotnet&seqNum=869 。

更多信息后更新

假设文件A中的数字列表足够小以适应内存,这就是你要做的事情,使用上面链接文章中的实现:

// Construct the automaton AhoCorasickStringSearcher matcher = new AhoCorasickStringSearcher(); foreach (var searchWord in File.ReadLines(File_a) { matcher.AddItem(searchWord); } matcher.CreateFailureFunction(); // And then do the search on each file foreach (var fileName in listOfFiles) { foreach (var line in File.ReadLines(filename)) { var matches = matcher.Search(line); foreach (m in matches) { // output match } } } 

请注意,它只会传递一个文件,并且它永远不必在任何时候将多行文件加载到内存中。 这里的限制因素是构建自动机所需的内存。

我已经用它来搜索总计超过100千兆字节的文件,大约有1500万个不同的字符串。 构建自动机需要几分钟,但随后搜索速度非常快。 该算法的一个非常好的属性是其复杂度为O(n + m),其中n是输入文件的大小,m是匹配项的数量。 它搜索的字符串数量无关紧要。 它可以搜索一百万个不同的字符串,就像搜索一个或两个字符串一样快。

100千兆字节将带你…大约40分钟阅读的东西。 如果花费一个小时的时间在100千兆字节的数据中找到所有出现的1500万个不同的字符串,我真的很惊讶。

匹配整个单词

另一种选择,如果你正在搜索整个单词,那就是放弃Aho-Corasick算法。 相反,将您要查找的所有数字加载到HashSet 。 然后读取每一行并使用正则表达式查找行中的所有数字,并检查它们是否存在于哈希集中。 例如:

 Regex re = new Regex("\w+"); foreach (var line in File.ReadLines(filename)) { var matches = re.Matchs(line); foreach (var m in matches) { if (hashSetOfValues.Contains(m)) { // output match } } } 

这可能比Aho-Corasick算法慢一些,但它仍然只通过数据一次。 当然,这假定您有足够的内存来保存哈希集中的所有这些数字。

正如我在评论中提到的那样,整个单词还有其他选择。

另一个选项是,如果您知道要查找的单词始终用空格分隔,则可以在添加到自动机的单词的开头和结尾添加空格。 或者,通过对实现本身的一些修改,您可以强制匹配器的Search方法仅返回整个单词中出现的匹配。 这可以更容易地处理行的开头和结尾处的匹配以及其他非单词字符。

 foreach (string _row in System.IO.File.ReadAllLines(AddressFilePath)) { if(_row.Contains(TextToSearch)){ //Do something Console.WriteLine(_row); } }