【问题标题】:Fastest way to find text in file在文件中查找文本的最快方法
【发布时间】:2020-08-04 05:45:03
【问题描述】:

所以我正在寻找一种方法来有效地搜索文件中的文本。现在我正在使用这个:

using (FileStream fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read, 1024 * 1024, FileOptions.SequentialScan))
using (StreamReader streamReader = new StreamReader(fileStream))
{
    string line;
    while ((line = streamReader.ReadLine()) != null)
    {
        int index = 0;
        while ((index = line.IndexOf(searchText, index, StringComparison.Ordinal)) != -1)
        {
            index += searchText.Length;
        }
    }
}

但是,我想知道是否有一种方法可以更有效地搜索文件。我正在考虑可能在缓冲区中搜索文本,但我不确定如何。 谢谢。

编辑: 如果不调用 IndexOf,我会得到大约 1600 毫秒。加上索引,大约是 7400ms。

编辑: 我有一个基本的块读取实现,它把时间缩短到了 740 毫秒。 (没有阅读线) 它还有很多工作要做,但我基本上一次读取一大块并获取索引。

【问题讨论】:

  • 这取决于瓶颈是什么,如果是文件读取,那么除了调整缓冲区大小之外,您不会变得更快。
  • this answer 有帮助吗?
  • @TheGeneral 我增加索引,因为我想找到该字符串中的所有匹配项。
  • 内存映射文件与否,您的文件读取可能会比实际搜索慢(如果我猜的话)
  • @VS-ux,你不会在这里得到答案,即使有人能想出一个好的答案,它可能会更快或更慢,具体取决于读取的特定文件,以及你是否想按行(和其他考虑)做到这一点。还有一些变量,例如您的 cpu 速度和 hdd 速度,它们将在等式中起作用。如果我是你(我相信你有能力),只要继续标杆,你就会找到最适合你的解决方案。 (注意,我删除了大部分 cmets,因为这已经失控了)

标签: c# .net string file


【解决方案1】:

从性能的角度来看,您的方法将是 O(xl) 时间,其中 x 是正在搜索的字符串的长度,l 是您尝试查找的字符串的长度。 您可以应用的通用算法很少:

  • 博耶-摩尔
  • 莫里斯-普拉特
  • 克努特-莫里斯-普拉特

我建议你使用 Boyer-Moore,这里有一些关于如何实现它的示例:https://www.geeksforgeeks.org/boyer-moore-algorithm-for-pattern-searching/

【讨论】:

  • 我在许多测试中看到 IndexOf 实际上仍然比 Boyer-Moore 快
  • String.IndexOf(string) 的当前实现使用一个简单的循环来检查某些给定文本的子字符串是否与模式匹配。虽然这个实现简单易懂,但效率很低,因为它必须遍历文本的最少 m - n + 1 个字符,其中 m 是文本的长度,n 是模式字符串的长度.
  • 但是在许多类似这样的测试中:blackbeltcoder.com/Articles/algorithms/… IndexOf 的表现优于boyer
  • 我用较大的块测试了 boyer moore(支持 boyer),但是,它仍然损失了近一半。
  • Boyer-Moore 被证明是最快的算法之一。 en.wikipedia.org/wiki/…。我不知道你现在的代码实现是什么以及在什么情况下,但从理论的角度来看,Boyer-Moore 是最好的方法。
猜你喜欢
  • 1970-01-01
  • 2010-11-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多