2009-09-01 7 views
42

Zlib :: GzipReader può prendere "un oggetto IO o simile all'IO". come è input, come indicato nei documenti.Come decomprimere la stringa Gzip nel rubino?

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 

Come si deve decomprimere una stringa?

risposta

105

Il metodo di cui sopra non ha funzionato per me.
Ho continuato a ricevere l'errore incorrect header check (Zlib::DataError). Apparentemente presume che tu abbia un'intestazione di default, il che potrebbe non essere sempre il caso.

Il lavoro in giro che ho implementato è stato:

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

Grazie, stavo ottenendo lo stesso errore e questo ha risolto il mio problema! –

+0

Aiuto Mucho anche qui – simonmorley

+0

sta chiamando body.to_s ridondante? – Blaskovicz

15

È necessario Zlib::Inflate per la decompressione di una stringa e Zlib :: Sgonfiare per la compressione

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

Zlib da asumes predefinite che i dati compressi contiene un'intestazione. Se i tuoi dati NON contengono un'intestazione falliranno sollevando un Zlib :: DataError.

Si può dire Zlib ad assumere i dati non ha alcuna intestazione tramite la seguente soluzione:

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

Questo non funziona più. – jm3

5

Utilizzando (-Zlib::MAX_WBITS), ho avuto ERROR: invalid code lengths set e ERROR: invalid block type
L'unica seguente funziona per me, anche.

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

ho usato la risposta di cui sopra per usare uno Zlib :: Sgonfiare

ho continuato a ottenere i file rotti (per file di piccole dimensioni) e ci sono voluti molte ore per capire che il problema può essere risolto utilizzando:

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

senza la riga zstream.finish!

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

a gunzip contenuto, l'uso seguente codice (testato su 1.9.2)

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

Beware of problemi di codifica

4

Non abbiamo bisogno di alcun parametro in più in questi giorni. Ci sono deflate e inflate metodi della classe che permettono di oneliners veloci come questi: "Come dovrei ungzip una stringa"

>> 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!" 

penso che risponde alla domanda il migliore. :)

+4

Se comprimi e decomprimi, questo andrà bene, ma non sarà compresso con gzip. L'esecuzione di Zlib :: Inflate.inflate (compressa) su dati compressi con gzip presuppone la compressione errata e genera un'eccezione "controllo intestazione errata". – philwhln

5

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

+1

Bello. Da [i documenti] (http://www.ruby-doc.org/stdlib-2.1.5/libdoc/zlib/rdoc/Zlib/Inflate.html) "o aggiungi 16 per decodificare solo il formato gzip (a Zlib: : DataError verrà generato per un flusso non gzip) " – iain

4

In Rails è possibile utilizzare:

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