2011-02-11 32 views
2

我需要做的是我有几个文件(txt)每个大约2GB。我需要削减文件让我们说每当'%% XGF NEW_SET'标记出现我需要创建新文件并将其存储。我认为这个标记大概每40-50行出现一次。每行有4-20个字符。 所以我需要将大文件切割成数千个小文件,然后再处理它们。我想到了这样的示例代码。高效的方式来读取和剪切文件

 DirectoryInfo di = new DirectoryInfo(ConfigurationManager.AppSettings["BilixFilesDir"]); 
     var files = di.GetFiles(); 
     int count = 0; 
     bool hasObject = false; 
     StringBuilder sb = new StringBuilder(); 
     string line = ""; 
     foreach (var file in files) 
     { 
      using (StreamReader sr = new StreamReader(file.FullName,Encoding.GetEncoding(1250))) 
      { 
       while ((line = sr.ReadLine()) != null) 
       { 
        //when new file starts 
        if (line.Contains("%%XGF NEW_SET")) 
        { 
         //when new file existed I need to store old one 
         if (hasObject) 
         { 
          File.WriteAllText(string.Format("{0}/{1}-{2}", ConfigurationManager.AppSettings["OutputFilesDir"], count++, file.Name), sb.ToString()); 
          sb.Length = 0; 
          sb.Capacity = 0; 

         } 
         //setting exist flag 
         hasObject = true; 
        } 
        //when there is no new object 
        else 
         //when object exists adding new lines 
         if (hasObject) 
          sb.AppendLine(line); 
       } 
       //when all work done saving last object 
       if (hasObject) 
       { 
        File.WriteAllText(string.Format("{0}/{1}-{2}", ConfigurationManager.AppSettings["OutputFilesDir"], count++, file.Name), sb.ToString()); 
        sb.Length = 0; 
        sb.Capacity = 0; 
       } 
      } 
     } 
    } 

所以我的例子看起来像那样,但我需要高效率。任何想法我可以改进我的解决方案?由于

+0

'%% XGF NEW_SET`是分割线上唯一的东西吗?如果没有,你正在失去其他信息,因为你正在扔掉这条线。 – 2011-02-11 14:47:58

回答

2

什么效率,你需要的排序,以你目前的代码会比较?个人而言,我可能会略微不同 - 让读者和作家随时打开,并写下你读的每一行,除非它是“剪切”行,在这种情况下,你只需关闭现有的作者并开始一个新的。尽管如此,我不会特别期待效率的不同。

1

我会完全消除对StringBuilder的需要,通过创建到被写入直到下一个对象来输出文件流。然后切换到新对象上的新文件流。

0

感谢您的所有提示。同时再考虑之后,我已经修改了我的代码为sommething这样的:

DirectoryInfo di = new DirectoryInfo(ConfigurationManager.AppSettings["BilixFilesDir"]); 
//getting all files from dir 
var files = di.GetFiles(); 
int count = 0; 
bool hasObject = false; 
string line = ""; 
StreamWriter sw = null; 
foreach (var file in files) 
{ 
    using (StreamReader sr = new StreamReader(file.FullName, Encoding.GetEncoding(1250))) 
    { 
     while ((line = sr.ReadLine()) != null) 
     { 
      //when new file starts 
      if (line.Contains("%%XGF NEW_SET")) 
      { 
       //when new file existed I need to store old one 
       if (hasObject) 
       { 
        sw.Close(); 
       } 
       else 
       { 
        //creating new file and setting exist flag 
        hasObject = true; 
        sw = new StreamWriter(string.Format("{0}/{1}-{2}", ConfigurationManager.AppSettings["OutputFilesDir"], count++, file.Name)); 
        //Bill bill = new Bill();        
       } 
      } 
      else 
       //when object exists adding new lines 
       if (hasObject) 
        sw.WriteLine(line); 
     } 
     //when all work done saving last object 
     if (hasObject) 
     { 
      sw.Close(); 
      hasObject = false; 
     } 
    } 
} 
sw.Dispose(); 

你怎么看待sommething这样呢?

还有一两件事,我需要做: 我的大文件可以存储不同的文档。他们都有不同的开始标志。 假设有20种文件。有时会有相同的标记开始,但在文档内部有一些额外的标记可以让我识别文档的类型。我的意思是,例如2个文件具有相同的标记开始像“%% XGF NEW_SET”但是你对后者像标记“BILL_A”和其他没有。而且我必须为每个剪切文件创建一个文件,其中包含文档中的一些索引以及包含该类型的字符串。所以在保存我的StreamWriter之前,我必须提取所有这些索引以及我对StringBuilder思考的文档类型。所以当我需要这种高效率时,这是下一个地方。任何好的提示?

0

有许多不同的方法来读取和.NET写出来的文件。我写了一个基准测试程序,并给予在我的博客的结果:

http://designingefficientsoftware.wordpress.com/2011/03/03/efficient-file-io-from-csharp

我建议使用Windows的ReadFile和WriteFile方法,如果你需要的性能。避免使用任何异步方法,因为我的基准测试结果表明,使用同步I/O方法可以获得更好的性能 - 至少对于FileStream来说,它是用于读取文件的最快.NET类。我在C#中编写了一个类,它封装了ReadFile和WriteFile功能使其非常易于使用。

另一个有趣的结果是,它看着东西就像读线.VS。以每个65,536字节的块读取数据并将其解析为行。事实证明,读取块中的数据,然后将其解析为程序内部的行更加高效。我的下载有一些如何做到这一点的例子。

我很喜欢它,如果你要下载它并试用它并在这里报告或者在我的博客上发表评论,如果它比StreamReader更快。根据我有限的基准,它显着更快。

提高程序性能的另一个想法是创建多个线程并让每个线程处理一个文件。既然你说过你有几个大文件,我会分解它,这样每个大文件都有一个单独的线程。

如果你使用字符串做了很多工作,那么你一定要使用StringBuilder。但是,也许更有效的方法是将数据读入一个字节数组,然后为输出构建一个字节数组。如果这不比使用StringBuilder更有效,我会感到惊讶。

Bob Bryan MCSD

相关问题