【问题标题】:Parsing variable length strings of fixed column widths C#解析固定列宽的可变长度字符串C#
【发布时间】:2012-09-20 14:42:21
【问题描述】:

我正在尝试解析格式化为列的文本报告。每列似乎都以固定长度右对齐。对于每一行,有时并非所有列都被使用。在这种情况下,似乎使用空格来证明行中的每一列。示例输入:

031   91    1221,154
043   66     312,222    1      3,047                       3,047    1.5%    .9%
040  118     529,626    1      1,842                       1,842     .8%    .3%
037   45     427,710
019   80     512,153    1     14,685                      14,685    1.2%   2.8%
009   68     520,301                      1    16,085     16,085    1.4%   3.0%
030   13     106,689                      1     1,581      1,581    7.6%   1.4%
008   54     377,593    1      7,098                       7,098    1.8%   1.8%
018   24     171,264
022   25       8,884    1        433                         433    4.0%   4.8%
035    9      42,043
041   13     112,355

列宽如下所示(按字符数计算,包括空格):3,5,12,6,10,7,10,11,8,7。

什么是解析这个的好方法?我曾尝试使用正则表达式来执行此操作,但在读入的第一行显然失败了,因为我使用的表达式希望整行都有数据:

字符串模式 = @"^(?.{3})(?.{5})(?.{12})(?thirtyeightyninenumber>.{6})(?{10})(?.{7 }(?.{10})(?.{11})(?.{8})(?.{7})";

根据该列是否有数据,寻找一种将其读入适当变量的好方法。我觉得我需要提交一堆if 签到,但我希望有更好的方法我没有想到。

感谢您的帮助。

顺便说一句 - 我正在使用 StreamReader 和 ReadLine 读取行。

【问题讨论】:

    标签: c# parsing fixed-width


    【解决方案1】:

    有一个TextFieldParser 专门用于读取这样的固定宽度/定界文本文件。

    它位于 Microsoft.VisualBasic.FileIO 命名空间中,但您仍然可以从 C# 中调用它。

    添加对Microsoft.VisualBasic的引用,一个using Microsoft.VisualBasic.FileIO;,那么代码如下:

    TextFieldParser parser = new TextFieldParser(stream);
    parser.TextFieldType = FieldType.FixedWidth;
    parser.SetFieldWidths(3, 5, 12, 6, 10, 7, 10, 11, 8, 7);
    while (!parser.EndOfData)
    {
        //Processing row
        string[] fields = parser.ReadFields();
    
        // Treat each field appropriately e.g. int.TryParse,
        // remove the "%" then float.TryParse etc.
    }
    parser.Close();
    

    编辑:也就是说,在 Reflector 中查看,我认为如果您的缩短线没有完整宽度的空格,这将失败。我不确定如何建议您解决此问题;您可以预处理您的流以在每行插入任何缺少的空格吗?

    【讨论】:

    • 我应该提一下,我对此进行了测试,这种方法在大文件上非常慢。 File.ReadLines() 工作得更快,然后我使用 Substring 来获取值。
    【解决方案2】:

    不要为此使用正则表达式。您知道列数和这些列的宽度,所以只需使用String.SubstringString.Trim

    string field1 = line.Substring(0, 5).Trim();
    string field2 = line.Substring(5, 3).Trim();
    string field3 = line.Substring(12, 8).Trim();
    /* etc, etc */
    

    【讨论】:

    • 与我的回答一样,这将在未填充最右侧列的行上失败,因为索引将超出范围。但是,我希望您的答案更容易适应克服这个问题:)
    • 我不知道谁投了反对票,因为我也在考虑 Substring 方法。 Rawling 给了我一些新的考虑(和学习),但是只需在输入行中添加填充,我想 Substring 将是最简单的解决方案(直到我学习 Rawlings 方法)。
    【解决方案3】:

    只需对照 myDataString + new string(' ', 1000) 检查您的正则表达式(或其他任何内容);

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-12-12
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多