2012-12-20 82 views
1

我不缺乏对字符串性能问题的搜索,但我仍然无法摆脱最好的方法。长期以来,我一直致力于从4NT转向PowerShell。在离开4NT时,我将错过名为FFIND的控制台超级快速字符串搜索实用程序。我决定使用我的基本C#编程技巧来尝试创建我自己的实用程序,以便在PowerShell中使用,同样快速。搜索字符串只需要第一次很长时间?

到目前为止,在几百个文件(其中一些非常大的文件)的100个目录中搜索字符串的搜索结果是FFIND 2.4秒和我的实用程序4.4秒.....在我至少运行过我的一旦????

我第一次运行它们FFIND几乎在同一时间,但我需要一分钟?这是什么?加载库?文件索引?我在代码中做错了什么?我不介意再等一会儿,但差别非常大,如果有更好的语言或方法,我宁愿在我投入太多之前开始沿着这条路走下去。

我需要选取其他语言编写一个字符串搜索将被点亮快速

我有必要利用这种工具通过文件1000来搜索网页代码,C#代码串,另一使用文本文件的预言性语言。我还需要能够使用此实用程序来查找非常大的日志文件(MB大小)中的字符串。

class Program 
{ 
    public static int linecounter; 
    public static int filecounter; 
    static void Main(string[] args) 
    { 
     // 
     //INIT 
     // 
     filecounter = 0; 
     linecounter = 0; 
     string word; 
     // Read properties from application settings. 
     string filelocation = Properties.Settings.Default.FavOne; 
     // Set Args from console. 
     word = args[0]; 
     // 
     //Recursive search for sub folders and files 
     // 
     string startDIR; 
     string filename; 
     startDIR = Environment.CurrentDirectory; 
     //startDIR = "c:\\SearchStringTestDIR\\"; 
     filename = args[1]; 
     DirSearch(startDIR, word, filename); 

     Console.WriteLine(filecounter + " " + "Files found"); 
     Console.WriteLine(linecounter + " " + "Lines found"); 
     Console.ReadKey(); 
    } 

    static void DirSearch(string dir, string word, string filename) 
    { 
     string fileline; 
     string ColorOne = Properties.Settings.Default.ColorOne; 
     string ColorTwo = Properties.Settings.Default.ColorTwo; 
     ConsoleColor valuecolorone = (ConsoleColor)Enum.Parse(typeof(ConsoleColor), ColorOne); 
     ConsoleColor valuecolortwo = (ConsoleColor)Enum.Parse(typeof(ConsoleColor), ColorTwo); 

     try 
     { 
      foreach (string f in Directory.GetFiles(dir, filename)) 
      { 
       StreamReader file = new StreamReader(f); 
       bool t = true; 
       int counter = 1; 
       while ((fileline = file.ReadLine()) != null) 
       { 
        if (fileline.Contains(word)) 
        { 
         if (t) 
         { 
         t = false; 
         filecounter++; 
         Console.ForegroundColor = valuecolorone; 
         Console.WriteLine(" "); 
         Console.WriteLine(f); 
         Console.ForegroundColor = valuecolortwo; 
         } 
         linecounter++; 
         Console.WriteLine(counter.ToString() + ". " + fileline); 
        } 
        counter++; 
       } 
       file.Close(); 
       file = null; 
      } 
      foreach (string d in Directory.GetDirectories(dir)) 
      { 
       //Console.WriteLine(d); 
       DirSearch(d,word,filename); 
      } 

     } 
     catch (System.Exception ex) 
     { 
      Console.WriteLine(ex.Message); 
     } 
    } 
} 
} 
+4

只是一个建议,但如果你绝望,有一个叫做grep的工具,在快速字符串搜索中是不可或缺的。 – cowboydan

+1

本地目录或网络资源?主硬盘或可能具有省电选项的辅助硬盘(例如N分钟后关闭等)?你运行FFIND然后尝试你的(或vise verse?)另外,如果FFIND使用非托管代码,它几乎总是比加载.NET更快。 –

+4

有很多现有的“在一堆文件中查找字符串的所有实例”程序,编写自己的程序并不值得,尤其是如果您在寻找性能。 (作为一种学习体验,当然,但不要打扰。) – JaredReisinger

回答

1

如果你想加快你的代码运行性能分析,看看什么是最花时间。我几乎可以guaruntee这里时间最长的步骤将是

fileline.Contains(word) 

这个函数被调用的文件的每一行,上的每个文件。天真地搜索字符串中的单词可以将len(字符串)* len(单词)比较。

您可以编写自己的Contains方法,该方法使用更快的字符串比较算法。谷歌的“快速字符串完全匹配”。你可以尝试使用正则表达式,看看是否能够提高性能。但我认为你可以尝试的最简单的优化是:

不要阅读每一行。制作一大串文件的所有内容。

StreamReader streamReader = new StreamReader(filePath, Encoding.UTF8); 
string text = streamReader.ReadToEnd(); 

运行包含此。

如果您需要文件中的所有匹配项,则需要使用类似Regex.Matches(string,string)之类的内容。

使用正则表达式获取单个文件的所有匹配之后,您可以迭代该匹配集合(如果有任何匹配)。对于每个匹配,您可以通过编写一个从匹配对象索引属性向前和向后读取函数的函数来恢复原始文件的行,以找到'\ n'字符。然后在这两条换行符之间输出该字符串,以获得您的行。

这样会快很多,我保证。

如果你想走得更远,有些事情我已经注意到有:

从外循环移除try catch语句。只能在你需要的地方使用它。我根本不会使用它。

还要确保你的系统正在运行,ngen。大多数设置通常都有,但有时ngen不运行。您可以在进程浏览器中看到进程。 Ngen生成C#托管字节码的原生图像,因此不必每次都解释代码,但可以原生运行。这加快了C#的速度。

编辑

其他景点: 为什么会出现第一个和后续运行时间之间的区别吗?看起来像缓存。操作系统可以缓存目录的请求,文件,用于运行和加载程序。通常在第一次运行后会看到加速。 Ngen也可以在这里扮演一个角色,在第一次运行编译后生成本地图像,然后将其存储在本机图像缓存中。

一般来说,我发现C#的性能因我的喜好而变得太多。如果建议的优化结果不令人满意,并且您希望获得更一致的性能结果,请尝试使用另一种语言 - 不是“托管”的语言。 C可能是您需要的最佳选择。

+0

将整个文件加载到内存中可能会变成一个坏主意,一旦你打到一个非常大的文件。此外,操作系统不会逐行读取文件,但(预)加载整个页面,因此加载更大的块将不会产生如人们所预期的那么大的改进。搜索文件几乎总是与I/O绑定的 - 在从磁盘读取页面时,您可以浏览大量内存。最后我怀疑用正则表达式可能会加快速度。可以将正则表达式编译为高效的状态机,但不能击败快速字符串搜索。 –

+0

这并没有回答问题 - 为什么在第一次和连续运行之间执行速度有显着差异。 –

+0

也许你应该尝试一下Daniel。 –

相关问题