У меня есть журнал файла, который я хотел бы проанализировать и имею некоторые проблемы. Сначала казалось, что это будет просто. Я буду идти вперед и отправлять источник, я придумал и затем объясняю, что я пытаюсь сделать.
Файл, который я пытаюсь проанализировать, содержит эти данные:
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
Мой исходный код (ниже) в основном разбивает файл линию за линией и затем разделяет строку на два (key:value).
Источник:
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
}
Проблема с моим источником - это, когда я использую свои методы считывания (такие как $dataList. Производительность), это только показывает последний в файле, а не два.
Таким образом, я задаюсь вопросом, как я анализирую файл так, чтобы он хранил информацию для обоих жестких дисков? Существует ли способ упаковать информацию в 'объект жесткого диска'?
Любой и вся справка ценятся
Несколько примечаний стороны:
Файл находится на машине окон (даже при том, что информация захватывается от отклонить системы),
Текстовый файл разделяется вкладкой, двоеточием, и пространство (как показанный в моем исходном коде) просто думало, что я заявлю это, потому что это не похоже на это на этой странице.
Это будет читать данные блоками (с пустыми строками, разделяющими блоки)
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"
}
}
Будем надеяться, что у вас есть пустые строки между секциями информации о HDD (вы показали одну в ваших тестовых данных) :-)
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)
Вот мое решение:
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"
}
}
}