在多个文件中搜索多个字符串

时间:2010-10-21 12:05:01

标签: c# string visual-studio-2010 file search

我有一个包含21000个字符串(每行一行)和500 MB其他文本文件(maily源代码)的文本文件。对于每个字符串,我需要确定它是否包含在任何这些文件中。我编写的程序可以完成这项工作,但是它的性能很糟糕(它会在几天内完成,我需要在最多5-6小时内完成工作)。
我正在使用C#,Visual Studio 2010编写

关于我的问题我有几个问题:
a)哪种方法更好?

foreach(string s in StringsToSearch)
{
    //scan all files and break when string is found
}

foreach(string f in Files)
{
    //search that file for each string that is not already found
}

b)逐行扫描一个文件是否更好

StreamReader r = new StreamReader(file);
while(!r.EndOfStream)
{
    string s = r.ReadLine();
    //... if(s.Contains(xxx));
}

StreamReader r = new StreamReader(file);
string s = r.ReadToEnd();
//if(s.Contains(xxx));

c)线程是否会提高性能以及如何做到这一点? d)是否有任何软件可以做到这一点,所以我不必编写自己的代码?

5 个答案:

答案 0 :(得分:6)

如果您只是想知道是否找到字符串,并且不需要进行任何进一步处理,那么我建议您只使用grep。 Grep非常快,专为解决这类问题而设计。

grep -f strings-file other-files...

应该做的伎俩。我确定那里有一个Windows实现。最糟糕的是,Cygwin会拥有它。

编辑:这回答问题d)

答案 1 :(得分:3)

您希望最小化文件I / O,因此您的第一个想法非常糟糕,因为您将打开“其他”文件达21.000次。你想使用基于第二个(a1)的东西。当其他文件不是太大时,用readAllText将它们加载到内存中一次。

List<string> keys = ...;    // load all strings

foreach(string f in Files)
{
    //search for each string that is not already found
    string text = System.IO.File.ReadAllText(f);  //easy version of ReadToEnd


    // brute force
    foreach(string key in keyes)
    {
        if (text.IndexOf(key) >= 0) ....
    }

}

蛮力部分可以改进,但我认为你会发现它是可以接受的。

答案 2 :(得分:2)

您可能希望在此处查看Windows Search SDK

http://msdn.microsoft.com/en-us/library/aa965362%28VS.85%29.aspx

答案 3 :(得分:2)

  1. 在a)和b)中,第二个选项都是有效的
  2. 线程可能无法提高每个线程从磁盘读取文件的性能,因此磁盘将成为瓶颈。
  3. sry我不知道你的目的是否为s / w
  4. 主题摘要

          foreach (FileInfo file in FileList)
          {
             Thread t  = new Thread(new ParameterizedThreadStart(ProcessFileData));
             t.Start(file.FullName);  
           }//where processFileData is the method that process the files
    

    常规I / O指南

    以下是一些减少程序I / O活动的基本建议,从而提高了性能。与所有建议一样,在优化之前和之后测量优化代码的性能非常重要,以确保它实际上变得更快。

    1. 最小化文件数量 您执行的操作
    2. 分组几个小的I / O传输 进入一个大转移。单身 写八页比快 八个单独的单页写入, 主要是因为它允许硬 磁盘一次写入数据 在磁盘表面上。更多 信息,
    3. 执行顺序读取而不是 寻找和阅读小块 数据。内核透明 集群I / O操作,这使得 顺序读取更快。
    4. 避免在空中跳过 写入数据前的文件。系统 必须写入零 填补空白以填补空白。 有关更多信息,请参阅阅读 通常比写作便宜 数据。
    5. 将任何I / O操作推迟到 指出你的应用程序实际上 需要数据。
    6. 使用首选项系统 仅捕获用户首选项(例如 作为窗口位置和视图 设置)而不是可以的数据 便宜地重新计算。
    7. 不要假设缓存文件数据 在记忆中会加快你的速度 应用。存储文件数据 记忆提高速度直到那 内存被换成磁盘,at 哪一点你支付的价格 再次访问磁盘。 努力寻找合适的人选 从磁盘读取之间的平衡 并在内存中缓存

答案 4 :(得分:2)

搜索是否必须是当前500 MB文本的实时? 我问的原因是因为你可以在文本文件上构建搜索索引并执行搜索。它会快得多......看看Lucene

Lucene.Net

C# and Lucene to index and search