我有一个包含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)是否有任何软件可以做到这一点,所以我不必编写自己的代码?
答案 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)
主题摘要
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活动的基本建议,从而提高了性能。与所有建议一样,在优化之前和之后测量优化代码的性能非常重要,以确保它实际上变得更快。
答案 4 :(得分:2)
搜索是否必须是当前500 MB文本的实时? 我问的原因是因为你可以在文本文件上构建搜索索引并执行搜索。它会快得多......看看Lucene