在文本文件中搜索字符串的更快方法
本文关键字:方法 字符串 搜索 文本 文件 | 更新日期: 2023-09-27 17:58:42
我需要使用C#在一组文本文件中搜索一个大约13个字符的字符串。文本文件的数量正在变化,范围可能在100-1000之间。文件的大小可以在1KB到10MB之间。
我尝试了一种天真的方法,打开每个文件,逐行读取,看看字符串是否存在(使用index.of),但这太慢了。我还尝试过使用Boyer-Moore算法,它确实将时间缩短了5秒,但仍然感觉很慢。
你知道如何加快搜索速度吗?
根据您要执行"搜索"的次数,您是否要使用搜索引擎。如果你想多次搜索,请使用搜索引擎,否则:不要。我将在这里描述如何实现这两种场景。
使用搜索引擎时:听起来你在寻找子字符串,这意味着你应该使用你最喜欢的搜索引擎,最好是你可以自定义的搜索引擎(lucene、terrier等)来索引你的文件。这里需要的技术是索引三元图,也就是说:所有3个字符的组合都必须被索引。F.例如:"foobar"将生成"foo"、"ob"、‘ba’和"bar"。在搜索时,您希望对查询执行同样的操作,并使用所有这些三元图的and发出搜索引擎查询。(这将在文档的发布列表上运行合并联接,它将返回文档的ID或您在发布列表中输入的任何内容)。
或者,您可以实现后缀数组并对文件进行一次索引。如果您想搜索短(1-2个字符)的子字符串,这将提供更多的灵活性,但在索引方面更难维护。(CWI/Amsterdam对快速索引后缀数组进行了一些研究)
当你只想搜索几次时,要使用的算法是Boyer-Moore(我通常使用Boyer-MooreSunday,如Graham a.Stephen,String search中所述)或编译的DFA(你可以从NFA构建它们,这更容易制作)。然而,这只会让你的速度略有提高,原因很简单,磁盘IO可能是你的瓶颈,而且比较你无论如何都需要解码的一堆字节是非常快的。
你能做的最大改进不是逐行读取文件,而是分块读取。如果可以的话,你应该将NTFS配置为使用64KB的块大小,并以64KB的倍数读取文件——想想一次读取4MB或更多。我甚至建议使用异步IO,这样您就可以同时读取和处理(以前读取的数据)。如果你做得正确,那么在大多数现代硬件上,这应该已经为你提供了一个10MB的瞬间实现。
最后但同样重要的是,在整个信息检索过程中使用的一个巧妙技巧也是使用快速压缩算法压缩数据。由于磁盘IO比内存/cpu操作慢,这可能也会有所帮助。谷歌的Snappy压缩器是快速压缩算法的一个很好的例子。
您应该考虑使用带有内容的操作系统文件搜索。查看Microsoft Windows Search 3.x SDK
或者,您可以使用PLINQ在文件阵列中进行搜索。请参阅此链接:
使用Directory.GetFiles和PLINQ 进行文件内容和目录搜索
想到两个选项:
在内存中读取文本文件,然后一次搜索整个字符串。
如果这被证明太慢或太占用内存,请使用ApacheLucene这样的索引器。有一个非常简单的SDK可以用于.NET,叫做Lucene.NET
这里有一个小介绍:http://www.codeproject.com/Articles/29755/Introducing-Lucene-Net
如果您的计算机能够处理它,请尝试将所有文本文件加载到内存中(使用此处显示的技术,然后评估内存中的文本。
如果不能同时处理所有文件,那么对最小的文件执行此操作。在这里,文件I/O将是您最大的开销,因此您需要尽可能地将其最小化。
您可以使用Microsoft的索引服务在要添加到目录中的文件夹中搜索文档。这是一篇非常好的文章,您可以使用它来搜索文本文件