2013-12-20 18 views
2

我需要解析日誌文件並將其轉換爲XML/Excel文件。日誌文件中有記錄數據的格式如下:如何解析變量空間分隔文本

Key_ID Property1 Property2 Property3 
Row1  value1iiii   value3 
Property4 
value4 
Key_ID Property1 Property2 Property3 
Row2   value1    value3 
Property4 
value4 

目前我試圖做到這一點在Java中,我需要比較XML轉換,而Excel的出口(我將使用Apache POI庫) 。問題是元素之間的可變間距,有時值可能爲空。目前我正在讀兩行並將它們存儲到一個字符串中,並嘗試使用掃描器,但這會錯過空白值,從而解析相應屬性的錯誤值。即使使用正則表達式,也會是同樣的問題。

感謝您提出寶貴的建議。我保留的數據僅供參考,我的意思是列數不同,有時候空白值可以在那裏。我已經瀏覽了將近50個這樣的日誌文件,而且我可以發現的常見事情是它會打印日誌文件,就好像我們從數據庫/ Excel表中複製和粘貼數據一樣。我能想到的唯一解決方案是逐行分析字符。 對不起,我無法立即回覆,我的寬帶連接已斷開。再次感謝您節省時間。

+0

Property2的值總是空的嗎? Property4總是在一個新的線上? –

+0

是否有可能列的固定大小可能是10個字符或每列都有它自己的大小? –

+0

不確定是否符合格式!該屬性是否可以包含空格,並且可以假定它們始終至少從列標籤「下」開始。 –

回答

0

如果兩個字段之間有空白,那麼您不能使用REGEX來完成。

但是,如果你的列有固定的寬度,那麼我的建議是逐行讀取文件。然後使用字符位置解析列。例如1-9是Key_ID,10-20是Property1,依此類推。

0

這是一個奇怪的格式。 但是,我會假設是的。 所以這是我會做的。 該代碼不是Java正確的。 這是更多的說明這個想法。

while (hasNext()) { // using some reader Scanner can probably work 
    String s = nextLine(); 
    if (s.startsWith("Key_ID")) { 
     String s1 = nextLine(); 
     // requires some complex parsing 
     // step 1 - split string into values 
     String s11 = s1.split("[ ]+"); 
     String property1 = null; 
     String property2 = null; 
     String property3 = null; 
     if (s11.length == 1) { // only key is present 
     } else if (s11.length == 2) { // two properties have blank values 
      // look in the next if block to see how that can expand to 2 blank values 
     } else if (s11.length == 3) { // one property have blank values 
      if (isBlank(10,20)) { // the text "Property1" 
       property2 = s11[1]; 
       property3 = s11[2]; 
      } else if (isBlank(20,30) { // the text "Property2" 
       property1 = s11[1]; 
       property3 = s11[2]; 
      } else { 
       property1 = s11[1]; 
       property2 = s11[2]; 
      } 
     } else { 
      property1 = s11[1]; 
      property2 = s11[2]; 
      property3 = s11[3]; 
     } 
     nextLine(); // skips the Property4 
     String property4 = nextLine(); 
    } 
} 

boolean isBlank(String s, int start, int end) { 
    // assumes that if there is a value it will be between the header text (e.g., Property1) 
    boolean result = true; 
    for (int i = start; i < end; i++) { 
     result &= s.charAt(i).equals(' '); 
    } 
    return result; 
} 

注意:有可能是一種方式,以進一步優化的代碼,但我並不想進入它,因爲代碼已經非常難看。我想指出的是,由於格式是人類可讀的,但不是計算機可讀的,代碼必須有些智能。

+0

謝謝@Chris,我已經發布了這個,如果偶然的人可能會遇到這種奇怪的格式,所以我會碰到一個魔法庫..:P。看起來,我必須走骯髒的路。在發佈之前,我實際上已經嘗試使用split(「\\ s +」)。 – saiki4116