2010-07-29 43 views
8

Tôi có nhật ký tệp mà tôi muốn phân tích cú pháp và đang gặp một số vấn đề. Lúc đầu, có vẻ như nó sẽ đơn giản. Tôi sẽ tiếp tục và đăng nguồn mà tôi đã đưa ra và sau đó giải thích những gì tôi đang cố gắng làm.Tệp văn bản phân tích cú pháp Groovy

File Tôi đang cố gắng để phân tích chứa dữ liệu này:

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 

mã nguồn của tôi (bên dưới) về cơ bản chia tay dòng tập tin bằng cách dòng và sau đó chia tách dòng thành hai (key: giá trị).

Nguồn:

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 
} 

Vấn đề với nguồn của tôi là khi tôi sử dụng thu khí của tôi (như $ dataList.Performance) nó chỉ cho thấy người cuối cùng trong file chứ không phải là hai.

Vì vậy, tôi tự hỏi, làm cách nào để phân tích cú pháp tệp để nó giữ thông tin cho cả hai ổ đĩa cứng? Có cách nào để đóng gói thông tin vào một 'đối tượng ổ đĩa cứng'?

Bất kỳ và tất cả help is appreciated

Một vài lưu ý phụ:

Các tập tin là trên một máy cửa sổ (mặc dù các thông tin được nắm lấy từ một hệ thống nix)

Các tập tin văn bản là chia cho một tab, dấu hai chấm và khoảng trống (như được hiển thị trong mã nguồn của tôi) chỉ nghĩ rằng tôi sẽ nói rằng vì nó không giống như trên trang này.

Trả lời

14

này sẽ đọc dữ liệu trong khối (với dòng trống tách các khối)

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" 
    } 
} 

Ngón tay vượt qua bạn có dòng trống giữa các phần thông tin HDD của bạn (bạn cho thấy một trong dữ liệu thử nghiệm của bạn) :-)

btw: tôi nhận được đầu ra sau đây:

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 

Messing arou nd, tôi cũng nhận được mã xuống:

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" 
    } 
} 

Nhưng điều đó có để tải toàn bộ tập tin vào bộ nhớ cùng một lúc (và dựa vào \n như EOL chấm dứt char)

+0

Ahh, sức mạnh của việc tiêm. ;) – Blacktiger

+1

Mọi người đều thích tiêm ;-) –

+0

Wow, cảm ơn chồi. Tôi không có ý làm phiền bạn, nhưng bạn có thể bình luận thứ hai, giống như bạn đã làm với cái đầu tiên? Hoặc nếu đó là quá nhiều công việc, có lẽ giải thích cách nó hoạt động. Cảm ơn bạn một lần nữa, thử nghiệm nó ra và hoạt động khá độc đáo. Theo như tải nó vào bộ nhớ, nó sẽ là tốt vì nó không phải là một số lượng lớn văn bản. – JohnStamos

5

Đây là giải pháp của tôi:

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

Điều này hoạt động khá độc đáo quá Cảm ơn nụ. Bạn có nhớ bình luận mã của bạn không? Bây giờ hai bạn đã đăng các ví dụ làm việc, tôi muốn biết mọi thứ hoạt động như thế nào trước khi tôi sử dụng nó:] – JohnStamos

Các vấn đề liên quan