2014-07-07 89 views
0

我想解析純文本格式的表。該程序使用C#編寫在Visual Studio中。我需要解析表格並將數據插入到數據庫中。解析純文本表

下面是一個示例表我將在被讀取:

ID Name   Value1  Value2   Value3  Value4 //header 
1  nameA   3.0   0.2   2   6.2 
2  nameB 
3  nameC   2.9       3.0   7.3 
4  nameD   1.5   3.0   1.8   1.1 
5  nameE 
6  nameF  1.2  2.4   3.3   2.5 
7  nameG  3.0  3.2   2.1   4.5 
8  nameH     88   12.4   28.9 

在示例中,我將需要捕獲數據以ID 1,3,4,6,7,和8

我想到了兩種方法來解決這個問題,但他們都沒有100%的工作。

方法1:

通過在頭部讀書,我可以得到每列的起始索引。然後我將使用Substring收集每行的數據。

ISSUE:一旦它經過某一行(我不知道什麼時候發生這種情況),列移位,並且Substring將不再收集正確的數據。

此方法只收集正確的數據爲1,3和4。

方法2:

使用Regex收集所有的匹配。我希望這可以按此順序收集ID,名稱,值1,值2,值3,值4。

我的模式是(\d*?)\s\s\s+(.*?)\s\s\s+(\d*\.*\d*)\s\s\s+(\d*\.*\d*)\s\s\s+(\d*\.*\d*)\s\s\s+(\d*\.*\d*)

問題,即收集一些行被左移數據。例如,在ID 3上,Value2應該爲空,但正則表達式將爲Value2 = 3.0,Value3 = 7.3Value4 = blank。同樣的問題也發生在ID 8

問:

我怎樣才能在全表中讀取並正確解析它們?

(1)我不知道開始從該行的值將被轉移並

(2)我不知道有多少細胞會通過,如果它們是一致的移動。

其他信息

表爲PDF文件,我轉換PDF到文本文件,這樣我就可以在數據讀取方面。移動數據發生在一張表跨越多個頁面時,但不一致。

編輯

下面是一些實際的數據:

68      BENZYL ALCOHOL        6.0       0.4   1     7.4 

91      EVERNIA PRUNASTRI (OAK MOSS)     34        3    3     10 

22      test                  2323   23     12 
+0

值是否有空格? – dognose

+0

表中是否有空格('')?如果不是的話,你可以只讀一行,並在所有空格處拆分並排除所有空字符串 – coolerfarmer

+0

@coolerfarmer認爲相同 - 但不起作用,因爲可能有空單元格。所以你不知道如何在4列上分配3個值。 (除非你建立一些容易出錯的邏輯,通過計算兩者之間的空格來確定它。) – dognose

回答

1

OK,這裏ü去!使用此正則表達式模式:

注意:您必須將此匹配到任何一行,而不是整個文檔!如果你想爲你的整個文檔做這個,那麼你必須添加'多行'修飾符('m')。您可以通過在正則表達式模式開始處添加(?m)來完成此操作!

編輯:

您提供您的真實數據的一些行。這裏是我更新後的正則表達式模式:

^(?<id>\d+)(?:\s{2,25})(?<name>.+?)(?:\s{2,45})(?<val1>\d+(?:\.\d+)?)?(?:\s{2,33})(?<val2>\d+(?:\.\d+)?)?(?:\s{2,14})(?<val3>\d+(?:\.\d+)?)?(?:\s{2,19})(?<val4>\d+(?:\.\d+)?)?$ 
+0

非常感謝你!我試過你的正則表達式,它適用於我提供的示例,但是,當我插入實際數據時,它不起作用。這是來自實際數據「68 BENZYL ALCOHOL 6.0 0.4 1 7.4」的一行,你能解釋爲什麼它沒有捕獲並幫助我修改它嗎? – sora0419

+0

好的,我會試試。你能給我多一行數據,所以我可以用它測試一下嗎? – coolerfarmer

+0

請參閱我的編輯,謝謝! – sora0419

1

如何處理這個文件就像一個固定長度的文件,在那裏你可以通過索引和長度定義每個列。一旦你定義了固定長度的列,你可以通過Substring然後Trim來得到列的值來清理它。

您可以將所有這些包裝在Linq語句中,投影到anonymouse類型並過濾所需的ID。

事情是這樣的:

static void Main(string[] args) 
{ 
    int[] select = new int[] { 1, 3, 4, 6, 7, 8 }; 
    string[] lines = File.ReadAllLines("TextFile1.txt"); 

    var q = lines.Skip(1).Select(l => new { 
     Id = Int32.Parse(GetValue(l, 0, 6)), 
     Name = GetValue(l, 6, 11), 
     Value1 = GetValue(l, 17, 11), 
     Value2 = GetValue(l, 28, 13), 
     Value3 = GetValue(l, 41, 14), 
     Value4 = GetValue(l, 55, 13), 
    }).Where(o => select.Contains(o.Id)); 

    var r = q.ToArray();   
} 

static string GetValue(string line, int index, int length) 
{ 
    string value = null; 
    int lineLength = line.Length; 

    // Take as much of the line as we can up to column length 
    if(lineLength > index)    
     value = line.Substring(index, Math.Min(length, lineLength - index)).Trim(); 

    // Return null if we just have whitespace 
    return String.IsNullOrWhiteSpace(value) ? null : value; 
}