2010-07-29 132 views
8

我有一個文件日誌,我想解析並有一些問題。起初,它似乎很簡單。我會繼續發佈我提出的源代碼,然後解釋我正在嘗試做的事情。Groovy解析文本文件

我試圖解析該文件包含了這樣的數據:

HDD Device 0 : /dev/sda 
HDD Model ID : ST3160815A 
HDD Serial No : 5RA020QY 
HDD Revision : 3.AAA 
HDD Size  : 152628 MB 
Interface : IDE/ATA 
Temperature   : 33 C 
Health : 100% 
Performance : 70% 
Power on Time : 27 days, 13 hours 
Est. Lifetime : more than 1000 days 

HDD Device 1 : /dev/sdb 
HDD Model ID : TOSHIBA MK1237GSX 
HDD Serial No : 97LVF9MHS 
HDD Revision : DL130M 
HDD Size  : 114473 MB 
Interface : S-ATA 
Temperature : 30 C 
Health : 100% 
Performance : 100% 
Power on Time : 38 days, 11 hours 
Est. Lifetime : more than 1000 days 

我的源代碼(下同)基本打破了由行的文件行,然後分割線分成兩個(鍵:值)。

來源:

def dataList = [:] 
def theInfoName = "C:\\testdata.txt" 

File theInfoFile = new File(theInfoName) 

def words 
def key 
def value 

if (!theInfoFile.exists()) { 
    println "File does not exist" 

} else { 

theInfoFile.eachLine { line -> 

if (line.trim().size() == 0) { 
    return null 

} else { 

    words = line.split("\t: ") 
    key=words[0] 
    value=words[1] 
    dataList[key]=value 

    println "${words[0]}=${words[1]}" 
    } 

} 
println "$dataList.Performance" //test if Performance has over-written the previous Performance value 
} 

與我的源的問題是,當我用我的getter方法(如$ dataList.Performance)只顯示了文件,而不是兩個在最後一節。

所以我想知道,我該如何解析文件,以便它保持兩個硬盤驅動器的信息?有沒有辦法將信息打包到「硬盤驅動器對象」中?

任何和所有幫助表示讚賞

一些旁註:

該文件是Windows的機器(即使信息是從尼克斯系統搶下)

的文本文件是在按標籤,冒號和空格拆分(如我的源代碼中所示),只是認爲我會說,因爲它看起來不像這個頁面。

回答

14

這將讀取的塊中的數據(用空行分隔塊)

def dataList = [] 
def theInfoName = 'testdata.txt' 

File theInfoFile = new File(theInfoName) 

if(!theInfoFile.exists()) { 
    println "File does not exist" 
} else { 
    def driveInfo = [:] 
    // Step through each line in the file 
    theInfoFile.eachLine { line -> 
    // If the line isn't blank 
    if(line.trim()) { 
     // Split into a key and value 
     def (key,value) = line.split('\t: ').collect { it.trim() } 
     // and store them in the driveInfo Map 
     driveInfo."$key" = value 
    } 
    else { 
     // If the line is blank, and we have some info 
     if(driveInfo) { 
     // store it in the list 
     dataList << driveInfo 
     // and clear it 
     driveInfo = [:] 
     } 
    } 
    } 
    // when we've finished the file, store any remaining data 
    if(driveInfo) { 
    dataList << driveInfo 
    } 
} 

dataList.eachWithIndex { it, index -> 
    println "Drive $index" 
    it.each { k, v -> 
    println "\t$k = $v" 
    } 
} 

手指交叉你有:-)

你的硬盤信息section(你教一個在您的測試數據)之間的空行

BTW:我得到以下輸出:

Drive 0 
    HDD Device 0 = /dev/sda 
    HDD Model ID = ST3160815A 
    HDD Serial No = 5RA020QY 
    HDD Revision = 3.AAA 
    HDD Size = 152628 MB 
    Interface = IDE/ATA 
    Temperature = 33 C 
    Health = 100% 
    Performance = 70% 
    Power on Time = 27 days, 13 hours 
    Est. Lifetime = more than 1000 days 
Drive 1 
    HDD Device 1 = /dev/sdb 
    HDD Model ID = TOSHIBA MK1237GSX 
    HDD Serial No = 97LVF9MHS 
    HDD Revision = DL130M 
    HDD Size = 114473 MB 
    Interface = S-ATA 
    Temperature = 30 C 
    Health = 100% 
    Performance = 100% 
    Power on Time = 38 days, 11 hours 
    Est. Lifetime = more than 1000 days 

醃肉梅辛第二,我也得到了代碼到:

def dataList = [] 
def theInfoFile = new File('testdata.txt') 

if(!theInfoFile.exists()) { 
    println "File does not exist" 
} else { 
    // Split the text of the file into blocks separated by \n\n 
    // Then, starting with an empty list go through each block of text in turn 
    dataList = theInfoFile.text.split('\n\n').inject([]) { list, block -> 
    // Split the current block into lines (based on the newline char) 
    // Then starting with an empty map, go through each line in turn 
    // when done, add this map to the list we created in the line above 
    list << block.split('\n').inject([:]) { map, line -> 
     // Split the line up into a key and a value (trimming each element) 
     def (key,value) = line.split('\t: ').collect { it.trim() } 
     // Then, add this key:value mapping to the map we created 2 lines above 
     map << [ (key): value ] // The leftShift operator also returns the map 
           // the inject closure has to return the accumulated 
           // state each time the closure is called 
    } 
    } 
} 

dataList.eachWithIndex { it, index -> 
    println "Drive $index" 
    it.each { k, v -> 
    println "\t$k = $v" 
    } 
} 

但是,有整個文件加載到內存中一次(和依賴\n作爲EOL終止字符)

+0

啊,注射的力量。 ;) – Blacktiger 2010-07-29 14:28:44

+1

大家都喜歡注入;-) – 2010-07-29 16:10:31

+0

哇,謝謝你。我並不是想打擾你,但是你能評論第二個,就像你對第一個做的那樣?或者如果這是太多的工作,也許解釋它是如何工作的。 再次感謝,測試它,並工作得非常好。至於將其加載到內存中,它應該沒問題,因爲它不是大量的文本。 – JohnStamos 2010-07-30 07:11:01

5

這裏是我的解決方案:

File file = new File('testdata.txt') 
if(file.exists()) { 
    def drives = [[:]] 
    // Split each line using whitespace:whitespace as the delimeter. 
    file.splitEachLine(/\s:\s/) { items -> 
     // Lines that did not have the delimeter will have 1 item. 
     // Add a new map to the end of the drives list. 
     if(items.size() == 1 && drives[-1] != [:]) drives << [:] 
     else { 
      // Multiple assignment, items[0] => key and items[1] => value 
      def (key, value) = items 
      drives[-1][key] = value 
     } 
    } 

    drives.eachWithIndex { drive, index -> 
     println "Drive $index" 
     drive.each {key, value -> 
      println "\t$key: $value" 
     } 
    } 
} 
+0

這一個很好地工作!感謝你,你介意評論你的代碼嗎?現在你們兩個已經發布了工作示例,我想知道在我使用它之前一切工作如何:] – JohnStamos 2010-07-30 07:12:18