最近做一个程序,有一个部分是统计某个文件夹内所有文件中包含某个关键词个数。
使用如下代码  效率很差
 /**//// <summary>
        /// 获取指定分类包含关键字或关键词的样本数目
        /// </summary>
        /// <param name="classification">指定分类</param>
        /// <param name="key">关键词或关键字</param>
        /// <returns>样本数目</returns>
        public int GetCountContainKeyOfClassification(string classification, string key)
        {
            int ret = 0;
            string[] filepaths = GetFilesPath(classification);
            try
            {
                
                for (int i = 0; i < filepaths.Length; i++)
                {
                    string text = GetFileText(filepaths[i]);
                    if (text.Contains(key))
                    {
                        ret++;
                    }
                }
            }
            catch
            {
                throw new Exception("error!");
            }
            return ret;
        }    }
}
不知道有没有更快的方法,请大家指教
因为文件夹内文件数目太多,平均每个文件夹下面都有1000-2000个TXT文件,所以总体计算起来很慢

解决方案 »

  1.   

    1.string text = GetFileText(filepaths[i]); 文本大不大,如果文本很大,这句是就是慢的根源. 
    如果1000-2000个TXT文本,每个文本很大的话,硬盘的读取速率是瓶颈,把1000-2000个很大的文本读入内存到string本身就是需要消耗很多的时间的.
    2. if (text.Contains(key)) <==这句话用来计数是不对滴,这个是判断文本中存不存在该字串,Contains在扫描到第一个匹配项时就会返回true,如果文本含有多个该关键字呢?
      

  2.   

    以下情况没有包含如果关键字跨行的情况.这种情况lz自行处理了
    比如我要搜索abcd
    第一行是 XXXXXab
    第二行是 cdXXXXX
    这类算不算匹配的关键字呢?
    using System;
    using System.Linq;
    using System.Data;
    using System.Data.SqlClient;
    using System.IO;
    using System.Text;
    using System.Diagnostics;namespace ConsoleApplication
    {
        namespace ConsoleApplication1
        {
            class Program
            {
                static void Main()
                {
                    //CreateHugeLineText();                //1.txt 609MB,1682W行,扫描匹配一次 13.4s 左右(CPU E2400, 7200转硬盘 , DDRII 800 2G X2)
                    Stopwatch time = new Stopwatch();
                    StreamReader sr = new StreamReader(@"d:\1.txt");
                    int TotalRowCount = 0;
                    int MatchedTime = 0;
                    time.Start();
                    while (sr.Peek() > 0)
                    {
                        TotalRowCount++;
                        if (sr.ReadLine().Contains("abcd"))
                        {
                            MatchedTime++;
                        }
                    }
                    time.Stop();
                    Console.WriteLine("Scanned {0} rows, Match {1} times,time elapsed:{2} s"
                                        , TotalRowCount.ToString()
                                        , MatchedTime.ToString()
                                        , time.Elapsed.TotalMilliseconds.ToString());
                    Console.ReadKey();                //2.txt 742KB, 2W行,扫描2000次共计40000w, 33.7s
                    time.Reset();
                    time.Start();
                    for (int t = 0; t < 2000; t++)
                    {
                        sr = new StreamReader(@"d:\2.txt");
                        while (sr.Peek() > 0)
                        {
                            TotalRowCount++;
                            if (sr.ReadLine().Contains("abcd"))
                            {
                                MatchedTime++;
                            }
                        }                }
                    time.Stop();
                    Console.WriteLine("Scanned {0} rows, Match {1} times,time elapsed:{2} s"
                                        , TotalRowCount.ToString()
                                        , MatchedTime.ToString()
                                        , time.Elapsed.TotalMilliseconds.ToString());
                    Console.ReadKey();
                }            static void CreateHugeLineText()
                {
                    StreamWriter sw = new StreamWriter(@"d:\2.txt", true, Encoding.UTF8);
                    int j = 0;
                    for (int i = 0; i < 20000; i++)
                    {
                        sw.WriteLine(System.Guid.NewGuid().ToString());
                        j++;
                        if (j >= 2000)
                        {
                            sw.Flush();
                        }
                        sw.Close();
                    }
                }
            }
        }
    }
      

  3.   

    //2.txt 742KB, 2W行,扫描2000次共计40000w, 33.7s
    ==> //2.txt 742KB, 2W行,扫描2000次共计4000w行, 33.7s呵呵 
      

  4.   

    感谢 上面两位大大,只要文章包含这个词就RET++就可以了  所以只要考虑#1说的第一条,应该如何改善这里的效率啊,谢谢了
    还有判断文章中是否包含关键词可以改善效率吗?
      

  5.   

    只有我一个人回帖... ... 如果仅仅只要这个文章包含这个词就RET++,你只要在 + 一句break;
    这样会大大的提高速度的,(只要这个关键词很不幸的每次都出现在每个文本的最后几行的话)
    我测试的例子,大概循环扫描2.txt 2000次 2秒就够了.  while (sr.Peek() > 0)
                        {
                            TotalRowCount++;
                            if (sr.ReadLine().Contains("abcd"))
                            {
                                MatchedTime++;
                                break; //这里
                            }
                        }