2011-12-30 37 views
8

Tôi có một file gzip và hiện nay tôi đọc nó như thế này:Làm cách nào để đọc một dòng tệp gzip theo dòng?

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

Tôi nghĩ rằng đây chuyển đổi tập tin vào một chuỗi, nhưng tôi muốn đọc nó từng dòng.

Những gì tôi muốn thực hiện là tệp có một số thông báo cảnh báo với một số rác, tôi muốn grep những thông báo cảnh báo đó và sau đó ghi chúng vào tệp khác. Tuy nhiên, một số thông điệp cảnh báo được lặp lại vì vậy tôi phải chắc chắn rằng tôi chỉ grep chúng một lần. Do đó dòng bằng cách đọc dòng sẽ giúp tôi.

Trả lời

17

Bạn sẽ có thể chỉ đơn giản lặp trên người đọc gzip như bạn làm với con suối thường xuyên (according to the docs)

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

Điều này có tự động đóng tệp sau khi đọc xong không? – Rohit

+3

Có và không - nếu GzipReader hoạt động trên một tập tin trực tiếp, bạn có thể muốn đóng nó. Nhưng trong trường hợp này, tôi giả sử phương thức 'mở' mở tập tin và do đó bạn phải đóng luồng IO nội tuyến. – Tigraine

+2

Wow !! 4 năm và vẫn trả lời bình luận về câu trả lời của bạn. Bây giờ là sự cống hiến !! Cảm ơn bạn lần nữa. – Rohit

1

Hãy thử điều này:

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

Sử dụng 'while' hoạt động, nhưng' each_line' như @Tigraine đã cho thấy, có nhiều thành ngữ hơn trong Ruby. –

+2

Tôi biết. Tôi thậm chí còn nghĩ đến việc xóa câu trả lời của tôi, nhưng sau đó quyết định rời khỏi nó, để hoàn thành. –

+2

Đó là một lý do chính đáng. Tôi định kỳ hiển thị các cách thay thế để thực hiện điều gì đó. Và, đó là vẻ đẹp của Ruby, chúng tôi có thể viết theo phong cách gần gũi hơn với cách chúng tôi đã học bằng các ngôn ngữ khác, giúp chúng dễ tiếp cận và dễ dàng hơn với chúng tôi với tư cách là người lập trình. Điều đó phù hợp với mục tiêu của Matz là nó minh bạch với nhà phát triển. –

1

câu trả lời khác cho thấy làm thế nào để đọc những dòng tập tin theo từng dòng, nhưng không phải cách chỉ ghi lại các lỗi một lần. Xây dựng trên câu trả lời của @ 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 

Đặt các hành vi như là mảng, nhưng chúng tôi chỉ quan tâm đến khóa, nhưng chỉ có giá trị duy nhất được lưu trữ. Nếu bạn cố gắng thêm các bản sao, chúng sẽ bị loại bỏ, chỉ để lại cho bạn những giá trị duy nhất. Bạn có thể sử dụng một Mảng, và sau đó sử dụng uniq, trên đó, nhưng Bộ sẽ quản lý nó cho bạn ở phía trước.

>> require 'set' 
=> true 
>> errors = Set.new 
=> #<Set: {}> 
>> errors << 'a' 
=> #<Set: {"a"}> 
>> errors << 'b' 
=> #<Set: {"a", "b"}> 
>> errors << 'a' 
=> #<Set: {"a", "b"}> 
Các vấn đề liên quan