2011-12-30 10 views
8

Mam plik gzip i obecnie czytam to tak:Jak czytać wiersz pliku gzip po linii?

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

myślę, że to konwertuje plik na sznurku, ale chciałbym, aby ją przeczytać wiersz po wierszu.

Co chcę osiągnąć, to, że plik zawiera kilka komunikatów ostrzegawczych z niektórymi śmieciami, chcę odszukać te komunikaty ostrzegawcze, a następnie zapisać je w innym pliku. Ale niektóre komunikaty ostrzegawcze są powtarzane, więc muszę się upewnić, że tylko raz je sprawdzę. W związku z tym mi pomógłaby linia po linii.

Odpowiedz

17

Powinieneś być w stanie po prostu pętla po czytniku gzip jak zrobić z regularnych strumieni (according to the docs)

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

Czy to powoduje automatyczne zamknięcie pliku po zakończeniu odczytu? – Rohit

+3

Tak i nie - jeśli GzipReader działa bezpośrednio na pliku, możesz go zamknąć. Ale w tym przypadku założyłem, że metoda "otwarta" otwiera plik, a tym samym trzeba zamknąć strumień "inline" IO. – Tigraine

+2

Wow !! 4 lata i wciąż odpowiada na komentarze na temat odpowiedzi. To jest dedykacja !! Jeszcze raz dziękuję. – Rohit

1

Spróbuj tego:

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

Używanie 'while' działa, ale' each_line' jako @Tigraine pokazało, jest bardziej idiomatyczne w Ruby. –

+2

Wiem. Myślałem nawet o usunięciu mojej odpowiedzi, ale potem postanowiłem ją opuścić, dla kompletności. –

+2

To dobry powód. Okresowo pokazuję alternatywne sposoby osiągnięcia czegoś. I to jest piękno Ruby, możemy pisać w stylach, które są bliższe temu, czego nauczyliśmy się w innych językach, co pomaga nam być bardziej dostępnym i przenośnym dla nas jako programistów. Było to zgodne z celem Matza, który był przejrzysty dla programisty. –

1

Inne odpowiedzi pokazują, jak czytać wiersz pliku według linii, ale nie w jaki sposób przechwytywać tylko błędy raz. Opierając się na @ odpowiedź Tigraine za:

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 

zestaw działa jak Array, ale jest zbudowany przy użyciu Hash, więc to jak Hash ale jesteśmy tylko o klawiszach, to znaczy tylko unikatowe wartości są przechowywane. Jeśli spróbujesz dodać duplikaty, zostaną one odrzucone, pozostawiając Ci tylko unikalne wartości. Możesz użyć Array, a następnie użyć uniq, ale Set będzie nim zarządzał z góry.

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