2009-09-01 13 views
42

Zlib :: GzipReader puede tomar "un objeto IO, o IO-like". como es entrada, como se indica en los documentos.¿Cómo descomprimir el hilo de Gzip en rubí?

Zlib::GzipReader.open('hoge.gz') {|gz| 
    print gz.read 
    } 

    File.open('hoge.gz') do |f| 
    gz = Zlib::GzipReader.new(f) 
    print gz.read 
    gz.close 
    end 

¿Cómo debo descomprimir una cadena?

Respuesta

105

El método anterior no funcionó para mí.
Obtuve el error incorrect header check (Zlib::DataError). Aparentemente, supone que tiene un encabezado por defecto, lo que puede no ser siempre el caso.

El trabajo en torno a que he implementado fue:

require 'zlib' 
require 'stringio' 
gz = Zlib::GzipReader.new(StringIO.new(resp.body.to_s))  
uncompressed_string = gz.read 
+3

Gracias, estaba obteniendo el mismo error y esto resolvió mi problema! –

+0

Mucho ayuda aquí también – simonmorley

+0

está llamando body.to_s redundante? – Blaskovicz

15

Usted necesita Zlib::Inflate para la descompresión de una cadena y Zlib :: desinflado para la compresión

def inflate(string) 
    zstream = Zlib::Inflate.new 
    buf = zstream.inflate(string) 
    zstream.finish 
    zstream.close 
    buf 
    end 
17

Zlib por defecto asumes que sus datos comprimido contiene un encabezado. Si sus datos NO contienen un encabezado, fallarán levantando un Zlib :: DataError.

Se puede decir Zlib para asumir el dato no tiene cabecera a través de la siguiente solución:

def inflate(string) 
    zstream = Zlib::Inflate.new(-Zlib::MAX_WBITS) 
    buf = zstream.inflate(string) 
    zstream.finish 
    zstream.close 
    buf 
end 
+0

Esto ya no funciona. – jm3

5

Usando (-Zlib::MAX_WBITS), tengo ERROR: invalid code lengths set y ERROR: invalid block type
La única siguientes obras para mí, también.

Zlib::GzipReader.new(StringIO.new(response_body)).read 
2

que utiliza la respuesta anterior de utilizar un Zlib :: desinflar

seguí recibiendo archivos en mal estado (para archivos pequeños) y se tomó muchas horas para darse cuenta de que el problema se puede solucionar usando:

buf = zstream.deflate(string,Zlib::FINISH) 

sin la línea zstream.finish!

def self.deflate(string) 
    zstream = Zlib::Deflate.new 
    buf = zstream.deflate(string,Zlib::FINISH) 
    zstream.close 
    buf 
end 
2

Para GUNZIP contenido, el uso siguiente código (probado en 1.9.2)

Zlib::GzipReader.new(StringIO.new(content), :external_encoding => content.encoding).read 

Cuidado con los problemas de codificación

4

No necesitamos ningún parámetro extra en estos días. Hay deflate y inflate métodos de clase que permiten oneliners rápidas como estas: "¿Cómo debería ungzip una cadena"

>> data = "Hello, Zlib!" 
>> compressed = Zlib::Deflate.deflate(data) 
=> "x\234\363H\315\311\311\327Q\210\312\311LR\004\000\032\305\003\363" 
>> uncompressed = Zlib::Inflate.inflate(compressed) 
=> "Hello, Zlib!" 

creo que responde a la pregunta el mejor. :)

+4

Si comprime y descomprime, esto estará bien, pero no se comprimirá gzip. Simplemente ejecutando Zlib :: Inflate.inflate (comprimido) en gzip los datos comprimidos asumirán la compresión incorrecta y arrojarán una excepción de "control de encabezado incorrecto". – philwhln

5

zStream = Zlib :: Inflate.new (16 + Zlib :: MAX_WBITS)

+1

Agradable. De [los documentos] (http://www.ruby-doc.org/stdlib-2.1.5/libdoc/zlib/rdoc/Zlib/Inflate.html) "o agregue 16 para decodificar solo el formato gzip (un Zlib: : DataError se generará para una secuencia que no sea gzip) " – iain

4

En Rails puede utilizar:

  • ActiveSupport::Gzip.compress("my string")
  • ActiveSupport::Gzip.decompress().
Cuestiones relacionadas