我需要使用C#在一组文本文件中搜索大约13个字符的字符串。文本文件的数量正在变化,范围在100-1000之间。文件大小可以在1KB到10MB之间。
我尝试了打开每个文件的天真方式,逐行读取并查看字符串是否存在(使用index.of),但这太慢了。我也尝试使用Boyer-Moore算法,它确实提高了时间,持续了5秒,但仍然感觉很慢。
关于如何加快搜索速度的想法?
答案 0 :(得分:8)
根据您要执行“搜索”的次数,您希望是否使用搜索引擎。如果您想要搜索很多次,请使用搜索引擎,否则:不要。我将在这里描述如何实现这两个场景。
使用搜索引擎时:听起来你正在寻找子串,这意味着你应该使用自己喜欢的搜索引擎索引你的文件,最好是你可以定制的(lucene,terrier等)。这里你需要的技术是索引三元组,即:所有3个字符的组合都必须被索引。 F.ex。:'foobar'将产生'foo','oob','oba'和'bar'。搜索时,您希望对查询执行相同操作,并使用所有这些三元组的AND发出搜索引擎查询。 (这将在文档的发布列表上运行合并连接,这将返回他们的ID或您在发布列表中放置的任何内容)。
或者,您可以实现后缀数组并将文件索引一次。如果要搜索短(1-2个字符)子字符串,这将提供更多的灵活性,但在索引方面更难维护。 (在CWI / Amsterdam有一些关于快速索引后缀数组的研究)
当您只想搜索几次时,要使用的算法是Boyer-Moore(我通常使用[Graham A. Stephen,String Search]中描述的Boyer-moore-sunday)或编译的DFA(你可以从NFA构建它们,这更容易制作)。但是,这只会给你一个小的速度增加,原因很简单,因为磁盘IO可能是你的瓶颈,并且比较你需要解码的一堆字节是非常快的。
您可以做的最大改进是不是逐行读取文件,而是以块为单位。如果可以,则应将NTFS配置为使用64 KB的块大小,并以64 KB的倍数读取文件 - 在单次读取中认为4 MB或更多。我甚至建议使用异步IO,以便您可以同时读取和处理(以前读取的数据)。如果你正确地执行它,那应该已经在大多数现代硬件上为你提供了10 MB的瞬间实现。
最后但同样重要的是,在整个信息检索过程中使用的一个巧妙的技巧也是使用快速压缩算法压缩数据。由于磁盘IO比内存/ CPU操作慢,这也可能有所帮助。谷歌的Snappy压缩器是快速压缩算法的一个很好的例子。
答案 1 :(得分:3)
您应该考虑对内容使用操作系统文件搜索。看看Microsoft Windows Search 3.x SDK
或者您可以利用PLINQ搜索文件数组。看到这个链接:
File Content and Directory Search using Directory.GetFiles and PLINQ
答案 2 :(得分:3)
有两种选择:
在内存中读取文本文件,只需一次搜索整个字符串。
如果证明太慢或者内存太大,请使用像Apache Lucene这样的索引器。有一个很好的,适用于.NET的SDK,名为Lucene.net
以下是它的一个小介绍: http://www.codeproject.com/Articles/29755/Introducing-Lucene-Net
答案 3 :(得分:1)
如果您的计算机可以处理它,请尝试将所有文本文件加载到内存中(使用technique shown here,然后评估内存中的文本。
如果您无法同时处理所有文件,请对最小的文件执行此操作。文件I / O将是您最大的开支,因此您希望尽可能减少这种情况。
答案 4 :(得分:1)
您可以使用Microsoft的索引服务来搜索要在目录中添加的文件夹中的文档。 Here是一篇非常好的文章,您可以使用它来搜索文本文件