【问题标题】:c# searching large text filec# 搜索大文本文件
【发布时间】:2012-12-19 19:10:53
【问题描述】:

我正在尝试优化对大型文本文件 (300-600mb) 中字符串的搜索。使用我目前的方法,耗时太长。

目前我一直在使用IndexOf 来搜索字符串,但是用字符串为每一行建立索引所花费的时间太长(20 秒)。

如何优化搜索速度?我试过Contains(),但这也很慢。有什么建议么?我在考虑正则表达式匹配,但我没有看到它有显着的速度提升。也许我的搜索逻辑有缺陷

例子

while ((line = myStream.ReadLine()) != null)
{
    if (line.IndexOf(CompareString, StringComparison.OrdinalIgnoreCase) >= 0)
    {
        LineIndex.Add(CurrentPosition);
        LinesCounted += 1;
    }
}

【问题讨论】:

  • 您到底在寻找什么?单词?
  • 您的 CompareString 是什么。请举例说明您要查找的内容。
  • 您确定这是您的搜索部分吗?不做任何检查只逐行读取文件需要多长时间?
  • 在不知道文件内容是什么以及您在其中搜索什么的情况下,这很难回答。如果您在文本文档中搜索短语与在按字母顺序排列的单词列表中搜索单词,则会得到截然不同的结果。
  • 对不起,让我指定我要搜索的内容。我正在查看一个大的日志文件,例如一行可以这样读取 61 - order for burger [9=1, 51=0, 59=1]。其中 9、51、59 是表示配料的哈希值(番茄酱 (9) = 是,蛋黄酱 (51) = 否,芥末(59) = 是。所以搜索可以是“订单”(显示所有订单)或“51 = 0'(显示所有未使用蛋黄酱的订单)。无需搜索,我可以在约 5 秒内逐行读取文件。但是通过搜索我实现的方式 - 它需要更长的时间。所以它绝对是我正在搜索的方式正在减慢它的速度

标签: c# search io full-text-search


【解决方案1】:

您使用的蛮力算法在 O(nm) 时间内执行,其中 n 是正在搜索的字符串的长度,而 m em> 您要查找的子字符串/模式的长度。您需要使用字符串搜索算法

但是,根据您要查找的内容,使用精心设计的正则表达式可能就足够了。请参阅 Jeffrey's Friedl 的著作,Mastering Regular Expressions 以获取有关构建高效正则表达式(例如,无回溯)的帮助。

您可能还想参考一个好的算法文本。我偏爱 Robert Sedgewick 的 Algorithms various incarnations[C|C++|Java] 中的算法

【讨论】:

  • 谢谢!我会尝试使用正则表达式搜索 - 如果它太慢。我将研究您上面列出的不同搜索算法
【解决方案2】:

不幸的是,我不认为你可以用纯 C# 做很多事情。

我发现 Boyer-Moore 算法对于这项任务非常快。但我发现没有办法做到像IndexOf 这样快。我的假设是这是因为IndexOf 是在手动优化的汇编程序中实现的,而我的代码是在 C# 中运行的。

你可以在文章Fast Text Search with Boyer-Moore看到我的代码和性能测试结果。

【讨论】:

  • hm 所以你会建议 IndexOf 是我搜索简单字符串的最快方法?到目前为止,使用这种方法已将我的文件读取增加到大约 30 秒。我想我会看看是否有任何替代方法可以提高搜索速度...
  • 是的,如果您的搜索区分大小写和区域性。否则,考虑因素会改变。
  • 不,我的搜索不区分大小写也不区分文化。简单的字符串文本搜索,想知道 IndexOf 是否是可以在 c# 中为此任务实现的最快的 - 如果是 - 那么我需要更改我的设计并选择另一个平台
  • 答案取决于您的需求。不知道你有没有看过我在原文章中引用的那篇文章。如果您进行不区分大小写的搜索,那么IndexOf() 会变得相当慢。在这种情况下,您可以尝试我在那篇文章中介绍的 Boyer-Moore 算法。对于超快速搜索,您需要建立一个索引。这取决于您的需求。
  • 谢谢,我只是在阅读它——我会在跳船之前尝试一些测试并查看 c# 的性能
【解决方案3】:

你看过这些问题(和答案)吗?

如果您只想阅读文本文件,那么按照您现在的方式进行操作似乎是可行的方法。其他想法:

  • 如果可以对数据进行预排序,例如在将数据插入文本文件时,这可能会有所帮助。

  • 您可以将数据插入数据库并根据需要进行查询。

  • 你可以使用哈希表

【讨论】:

    【解决方案4】:

    您可以使用 regexp.Match(String)。正则表达式匹配更快。

    静态 void Main()

    {

      string text = "One car red car blue car";
      string pat = @"(\w+)\s+(car)";
    
      // Instantiate the regular expression object.
      Regex r = new Regex(pat, RegexOptions.IgnoreCase);
    
      // Match the regular expression pattern against a text string.
      Match m = r.Match(text);
      int matchCount = 0;
      while (m.Success) 
      {
         Console.WriteLine("Match"+ (++matchCount));
         for (int i = 1; i <= 2; i++) 
         {
            Group g = m.Groups[i];
            Console.WriteLine("Group"+i+"='" + g + "'");
            CaptureCollection cc = g.Captures;
            for (int j = 0; j < cc.Count; j++) 
            {
               Capture c = cc[j];
               System.Console.WriteLine("Capture"+j+"='" + c + "', Position="+c.Index);
            }
         }
         m = m.NextMatch();
      }
    

    }

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-03-10
      • 1970-01-01
      • 2016-01-21
      • 2012-10-03
      • 1970-01-01
      • 1970-01-01
      • 2018-05-08
      • 2023-03-28
      相关资源
      最近更新 更多