2011-12-30 29 views
8

Tengo un archivo gzip y actualmente lee así:¿Cómo leo un archivo gzip línea por línea?

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

creo que esto convierte el archivo en una cadena, pero me gustaría leer línea por línea.

Lo que quiero lograr es que el archivo tenga algunos mensajes de advertencia con algo de basura, quiero agregar esos mensajes de advertencia y luego escribirlos en otro archivo. Pero algunos mensajes de advertencia se repiten, así que tengo que asegurarme de que solo los grepé una vez. Por lo tanto, la lectura línea por línea me ayudaría.

Respuesta

17

usted debería ser capaz de simplemente un bucle sobre el lector gzip como se hace con los flujos regulares (according to the docs)

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

¿Esto cierra automáticamente el archivo una vez que se completa la lectura? – Rohit

+3

Sí y no: si el GzipReader funciona directamente en un archivo, es posible que desee cerrarlo. Pero en este caso asumí que el método 'open' abre el archivo y, por lo tanto, tiene que cerrar la secuencia de IO' en línea'. – Tigraine

+2

¡Guau! 4 años después y aún respondiendo a los comentarios de su respuesta. ¡¡¡Eso es dedicación !! Gracias de nuevo. – Rohit

1

Prueba esto:

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

Uso de 'while' funciona, pero' each_line' como mostró @Tigraine, es más idiomático en Ruby. –

+2

Lo sé. Incluso pensé en eliminar mi respuesta, pero luego decidí dejarla, para completarla. –

+2

Esa es una buena razón. Periódicamente, muestro formas alternativas de lograr algo. Y, esa es la belleza de Ruby, podemos escribir en estilos que están más cerca de cómo hemos aprendido en otros idiomas, lo que lo hace más accesible y portátil para nosotros como programadores. Eso estaba en línea con el objetivo de Matz de ser transparente para el desarrollador. –

1

Otras respuestas muestran cómo leer el archivo línea por línea, pero no cómo solo capturar los errores una vez. Sobre la base de la respuesta de @ 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 

Set actúa como matriz, pero se construye a partir de hash, así que es como un hash pero estamos sólo se ocupa de las teclas, es decir, sólo valores únicos se almacenan. Si intentas agregar duplicados, se descartarán, dejándote solo con los valores únicos. Puede usar una matriz y luego usar uniq, pero un conjunto lo administrará por adelantado.

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