2012-09-20 163 views
2

我想解析格式化为列的文本报告。每列看起来都是右对齐的,长度固定。对于每一行,有时并不是所有的列都被使用。在这种情况下,似乎用空格来证明该行中的每一列。示例输入:解析固定列宽度的可变长度字符串C#

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。

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

string pattern = @“^(?. {3})(?。{5})(?。{12})(?thirtyeightyninenumber>。{6})({10})(?{7}(?。{10})(?{ 11})(?。{8})(?。{7})“;

寻找一个很好的方法来将它读入合适的变量,具体取决于该列是否有数据。扔在一堆if检查,但我希望有一个更好的办法,我没有想到的。

感谢您的帮助。

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

回答

6

请勿对此使用正则表达式。你知道列和这些列的宽度的数量,因此就使用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 */ 
+0

任何意见与反对表决? –

+1

与我的答案一样,在最右侧列未填充的行上,这将失败,因为索引将超出范围。然而,你的答案将更容易适应克服这一点,我期望:) – Rawling

+0

我不知道是谁投了票,因为我正在考虑Substring方法。 Rawling给了我一些新的思考(并学习),但只需在输入行中添加填充,我认为Substring是最简单的解决方案(直到我学习Rawlings方法)。 – Shawn

7

有可用的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(); 

编辑:也就是说,寻求在反射器,我认为,如果你缩短线路没有完全失败宽度值的空间。我不知道如何建议你解决这个问题。你可以预处理你的流来插入每行缺失的空格吗?

-1

只需检查你的正则表达式(或任何其他)对myDataString +新字符串('',1000);