2011-12-30 189 views
8

我有一個gzip文件,目前我讀到這樣的:如何逐行讀取gzip文件?

infile = open("file.log.gz") 
gz = Zlib::GzipReader.new(infile) 
output = gz.read 
puts result 

我覺得這個轉換文件爲一個字符串,但我想逐行讀它。

我想完成的是該文件有一些垃圾警告消息,我想grep這些警告消息,然後將它們寫入到另一個文件。但是,一些警告信息是重複的,所以我必須確保我只grep他們一次。因此,逐行閱讀會幫助我。

回答

17

你應該能夠簡單地遍歷gzip的讀者喜歡你用常規的流(according to the docs

infile = open("file.log.gz") 
gz = Zlib::GzipReader.new(infile) 
gz.each_line do |line| 
    puts line 
end 
+0

這會在閱讀完成後自動關閉文件嗎? – Rohit 2015-08-14 20:49:10

+3

是,否 - 如果GzipReader直接在文件上運行,您可能需要關閉它。但在這種情況下,我假定'open'方法打開文件,因此您必須關閉'inline' IO流。 – Tigraine 2015-08-24 08:21:00

+2

哇! 4年後,仍然回覆對你的回答的評論。 現在,這是奉獻! 再次感謝。 – Rohit 2015-08-25 04:47:27

1

試試這個:

infile = open("file.log.gz") 
gz = Zlib::GzipReader.new(infile) 
while output = gz.gets 
    puts output 
end 
+1

使用'while'作品,但@Tigraine的'each_line'在Ruby中更具慣用性。 – 2011-12-30 23:31:28

+2

我知道。我甚至想過刪除我的答案,但後來決定離開它,爲了完整性。 – 2011-12-30 23:34:27

+2

這是一個很好的理由。我定期展示替代方式來完成某件事。而且,這就是Ruby的美妙之處,我們可以用更接近於其他語言學習的風格編寫代碼,這有助於我們作爲程序員更易於訪問和移植。這符合Matz對開發人員透明的目標。 – 2011-12-30 23:41:57

1

其他的答案顯示瞭如何讀取文件中的行做而不是如何只捕捉一次錯誤。建立在@ Tigraine的回答是:

require 'set' 

infile = open("file.log.gz") 
gz = Zlib::GzipReader.new(infile) 

errors = Set.new 
# or ... 
# errors = [].to_set 

gz.each_line do |line| 
    errors << line if (line[/^Error:/]) 
    # or ... 
    # errors << line if (line['Error:']) 
end 

puts errors 

設置的行爲像數組,但使用Hash建成,所以它就像一個哈希但我們只關心鍵,即唯一的值存儲。如果您嘗試添加重複項,則它們將被丟棄,僅留下唯一的值。你可以使用一個數組,然後使用uniq,但是一個Set會在你前面管理它。

>> require 'set' 
=> true 
>> errors = Set.new 
=> #<Set: {}> 
>> errors << 'a' 
=> #<Set: {"a"}> 
>> errors << 'b' 
=> #<Set: {"a", "b"}> 
>> errors << 'a' 
=> #<Set: {"a", "b"}>