2009-09-01 15 views
42

Zlib :: GzipReader może przyjmować obiekt "IO lub IO-like". jako dane wejściowe, zgodnie z dokumentami.Jak rozpakować ciągi Gzip w ruby?

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 

Jak powinienem odpiąć sznur?

Odpowiedz

105

powyższa metoda nie działa dla mnie.
Ciągle otrzymuję błąd incorrect header check (Zlib::DataError). Wygląda na to, że domyślnie masz nagłówek, co nie zawsze musi mieć miejsce.

Prace wokół, że realizowany był:

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

Dziękuję, otrzymałem ten sam błąd i to rozwiązało mój problem! –

+0

Mucho pomoc tutaj też – simonmorley

+0

dzwoni do body.to_s redundant? – Blaskovicz

15

Trzeba Zlib::Inflate do dekompresji ciąg i zlib :: DEFLATE kompresji

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

Zlib domyślnie asumes że skompresowane dane zawierają nagłówek. Jeśli twoje dane NIE zawierają nagłówka, nie powiedzie się, zgłaszając błąd Zlib :: DataError.

Można powiedzieć Zlib zakładać danych nie posiada nagłówka za pomocą następującego rozwiązania:

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

To już nie działa. – jm3

5

Korzystanie (-Zlib::MAX_WBITS), mam ERROR: invalid code lengths set i ERROR: invalid block type
Jedynym następujące prace dla mnie.

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

Kiedyś odpowiedź powyżej użyć Zlib :: Deflate

Ciągle coraz uszkodzone pliki (dla małych plików) i zajęło wiele godzin, aby dowiedzieć się, że problem można rozwiązać przy użyciu:

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

bez linii zstream.finish!

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

Aby gunzip materiałów, użyj poniższego kodu (testowane na 1.9.2)

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

Strzeż problemów kodowania

4

Nie potrzeba żadnych dodatkowych parametrów w tych dniach. Istnieje deflate i inflate metody klasy, które pozwalają na szybkie oneliners takie jak: „Jak mam ungzip ciąg”

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

Myślę, że odpowiedź na pytanie najlepszy. :)

+4

Jeśli kompresujesz i dekompresujesz, to będzie dobrze, ale nie będzie skompresowany gzip. Uruchomienie Zlib :: Inflate.inflate (skompresowanego) na skompresowanych danych gzip przybierze błędną kompresję i wyrzuci wyjątek "niepoprawnego sprawdzania nagłówka". – philwhln

5

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

+1

Niezły. Od [the docs] (http://www.ruby-doc.org/stdlib-2.1.5/libdoc/zlib/rdoc/Zlib/Inflate.html) "lub dodać 16, aby odszyfrować tylko format gzip (Zlib: : DataError zostanie podniesiony dla strumienia innego niż gzip) " – iain

4

W Rails można użyć:

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