2010-07-29 124 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