高效处理顺序文件C#

时间:2016-06-20 14:22:53

标签: c# file-processing

我正在开发一个处理由Cobol系统生成的顺序文件的系统,目前,我正在使用几个子串进行数据处理以获取数据,但我想知道是否有更有效的方法来处理文件而不是制作几个子串...

现在,我基本上做了:

using (var sr = new StreamReader("file.txt"))
{
    String line = "";
    while(!sr.EndOfStream)
    {
        line = sr.ReadLine();
        switch(line[0])
        {
            case '0':
                processType0(line);
                break;
            case '1':
                processType1(line);
                break;
            case '2':
                processType2(line);
                break;
            case '9':
                processType9(line);
                break;
        }
    }
}

private void processType0(string line)
{
    type = line.Substring(0, 15);
    name = line.Substring(15, 30);
    //... and more 20 substrings
}

private void processType1(string line)
{
    // 45 substrings...
}

文件大小可能在50mb到150mb之间变化...... 文件的一个小例子:

01ARQUIVO01CIVDSUQK       00000000000000999999NAME NAME NAME NAME           892DATAFILE       200616        KY0000853                                                                                                                                                                                                                                                                                     000001
1000000000000000000000000999904202589ESMSS59365        00000010000000000000026171900000000002            0  01000000000001071600000099740150000000001N020516000000000000000000000000000000000000000000000000000000000000009800000000000000909999-AAAAAAAAAAAAAAAAAAAAAAAAA                                                            00000000                                                            000002
1000000000000000000000000861504202589ENJNS63198        00000010000000000000036171300000000002            0  01000000000001071600000081362920000000001N020516000000000000000000000000000000000000000000000000000000000000009800000000000000909999-BBBBBBBBBBBBBBBBBBBBBBBBBB                                                           00000000                                                            000003
9                                                                                                                                                                                                                                                                                                                                                                                                         000004

4 个答案:

答案 0 :(得分:2)

频繁的磁盘读取会降低代码速度。

根据MSDN,constructor you are using的缓冲区大小为1024字节。 使用不同的构造函数设置更大的缓冲区大小:

int bufferSize = 1024 * 128;

using (var reader = new StreamReader(path, encoding, autoDetectEncoding, bufferSize))
{
   ...
}

C#优先考虑安全性超速,因此所有String函数都会生成一个新字符串。

你真的需要所有这些子串吗?如果没有,那么只需生成你需要的那些:

private static string GetType(string line)
{
    return line.Substring(0, 15);
}

if (needed)
    type = GetLine(line);

答案 1 :(得分:1)

您可以尝试编写一个解析器,一次处理一个字符。

我读了一篇名为' Writing a parser for CSV data'关于如何使用CSV文件进行此操作的日子,尽管大多数文件类型的主体是相同的。这可以在http://www.boyet.com/articles/csvparser.html

找到

答案 2 :(得分:1)

第一次使用C#,但我想你想看看像

这样的东西
struct typeOne {
    fixed byte recordType[1];
    fixed byte whatThisFieldIsCalled[10];
    fixed byte someOtherFieldName[5];
    ...
}

然后只按行[0]大小写分配不同的结构。或者,知道Nada旁边有关C#的内容,这可能是完全错误的球场,并最终在内部表现不佳。

答案 3 :(得分:0)

我爱Linq

IEnumerable<string> ReadFile(string path)
{
 using (var reader = new StreamReader(path))
  {
    while (!reader.EndOfStream)
    {
     yield return reader.ReadLine();
    }
  }
}


void DoThing() 
{
  var myMethods = new Action<string>[] 
    { 
      s => 
         {
           //Process 0            
           type = line.Substring(0, 15);
           name = line.Substring(15, 30);
           //... and more 20 substrings
         },
      s => 
         {
           //Process 1            
           type = line.Substring(0, 15);
           name = line.Substring(15, 30);
           //... and more 20 substrings
         },
            //...

    }

var actions = ReadFile(@"c:\path\to\file.txt")
      .Select(line => new Action( () => myMethods[int.Parse(line[0])]() ))
      .ToArray();

 actions.ForEach(a => a.Invoke());
}