优化C#文件IO

时间:2011-01-20 19:09:44

标签: c# optimization file-io

场景 - 150MB文本文件,它是旧电子邮件帐户的导出收件箱。需要解析并从特定用户中提取电子邮件并将其写入新的单个文件。我有适用的代码,它只是顽强的慢。

我正在使用标记字符串来搜索从原始文件开始/结束副本的位置。

这是主要功能:

 StreamReader sr = new StreamReader("c:\\Thunderbird_Inbox.txt");
        string working = string.Empty;
        string mystring = string.Empty;
        while (!sr.EndOfStream)
        {
            while ((mystring = sr.ReadLine()) != null)
            {
                if (mystring == strBeginMarker)
                {
                    writeLog(mystring);

                    //read the next line
                    working = sr.ReadLine();

                        while( !(working.StartsWith(strEndMarker)))
                        {
                            writeLog(working);
                            working = sr.ReadLine();

                        }
                  }
            }

        }
        this.Text = "DONE!!";
        sr.Close();

将所选消息写入新文件的功能:

  public void writeLog(string sMessage)
    {
            fw = new System.IO.StreamWriter(path, true);
            fw.WriteLine(sMessage);
            fw.Flush();
            fw.Close();
    }

同样,这个过程有效。我得到了一个好的输出文件,它只需要很长时间,我确信有办法让它更快。

5 个答案:

答案 0 :(得分:19)

最大的优化是更改writeLog方法,在此操作开始时打开文件一次,多次写入,然后在最后关闭它。

现在,你在每次迭代时打开和关闭文件,这肯定会减慢速度。

尝试以下方法:

// Open this once at the beginning!
using(fw = new System.IO.StreamWriter(path, true))
{
    using(StreamReader sr = new StreamReader("c:\\Thunderbird_Inbox.txt"))
    {
        string working;
        string mystring;
        while ((mystring = sr.ReadLine()) != null)
        {
           if (mystring == strBeginMarker)
           {
                writeLog(mystring);

                //read the next line
                working = sr.ReadLine();

                while( !(working.StartsWith(strEndMarker)))
                {
                    fw.WriteLine(working);
                    working = sr.ReadLine();
                }
            }
        }
    }
}
this.Text = "DONE!!";

答案 1 :(得分:2)

我认为你应该:

  1. 打开文件一次。
  2. 将源文件加载到内存中。
  3. 打破它并使用多个线程进行处理。

答案 2 :(得分:2)

我只是做一个简单的解析器。请注意,这假定(与上面的代码一样)标记实际上是唯一的。

您可能需要使用输出的一些格式,但这是一般的想法:

   // Read the entire file and close it
   using (StreamReader sr = new
   StreamReader("c:\\Thunderbird_Inbox.txt");)
   {
       string data = sr.ReadToEnd();   
   }

   string newData = "";   
   int position = data.IndexOf(strBeginMarker);

   while (position > 0)   
   {
      int endPosition = data.IndexOf(endMarker, position);
      int markerLength = position + strBeginMarker.Length;

     newData += data.Substring(markerLength, endPosition - markerLength);

     position = data.IndexOf(strBeginMarker, position+ endStr.Length);   
   }

  writeLog(newData);

(请注意,我没有150 MB的文件来测试它 - YMMV,具体取决于您使用的机器。)

答案 3 :(得分:0)

我没有要测试的150MB文本文件,但是如果你的服务器有内存就会把hold东西读成一个字符串并执行一个RegEx拉出消息工作?

答案 4 :(得分:0)

您可以简单地在该while循环之外声明StreamWriter对象,并在循环内部将该行写入其中。

像这样:

StreamWriter sw = new StreamWriter(path, true);
while
{
    // ...
    while( !(working.StartsWith(strEndMarker)))
    {
        sw.WriteLine(working);
        working = sr.ReadLine();
    }
}