2012-09-20 198 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);