Как распаковать строку Gzip в ruby? - PullRequest
47 голосов
/ 01 сентября 2009

Zlib :: GzipReader может принимать «объект ввода-вывода или IO-подобный объект». как это указано, как указано в документах.

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

Как мне распаковать строку?

Ответы [ 9 ]

113 голосов
/ 02 сентября 2009

Вышеуказанный метод не работает для меня.
Я продолжал получать incorrect header check (Zlib::DataError) ошибку. По-видимому, предполагается, что у вас есть заголовок по умолчанию, что не всегда так.

Обход, который я реализовал, был:

require 'zlib'
require 'stringio'
gz = Zlib::GzipReader.new(StringIO.new(resp.body.to_s))    
uncompressed_string = gz.read
18 голосов
/ 15 ноября 2009

Zlib по умолчанию предполагает, что ваши сжатые данные содержат заголовок. Если ваши данные НЕ содержат заголовок, они потерпят неудачу, подняв Zlib :: DataError.

Вы можете сказать Zlib, что предполагается, что данные не имеют заголовка, с помощью следующего обходного пути:

def inflate(string)
  zstream = Zlib::Inflate.new(-Zlib::MAX_WBITS)
  buf = zstream.inflate(string)
  zstream.finish
  zstream.close
  buf
end
15 голосов
/ 01 сентября 2009

Вам нужно Zlib :: Inflate для распаковки строки и Zlib :: Deflate для сжатия

  def inflate(string)
    zstream = Zlib::Inflate.new
    buf = zstream.inflate(string)
    zstream.finish
    zstream.close
    buf
  end
7 голосов
/ 16 января 2014

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

6 голосов
/ 13 ноября 2015

В Rails вы можете использовать:

  • ActiveSupport::Gzip.compress("my string")
  • ActiveSupport::Gzip.decompress().
5 голосов
/ 26 декабря 2009

Используя (-Zlib::MAX_WBITS), я получил ERROR: invalid code lengths set и ERROR: invalid block type
У меня тоже работает только следующее.

Zlib::GzipReader.new(StringIO.new(response_body)).read
3 голосов
/ 18 сентября 2012

Нам не нужны никакие дополнительные параметры в эти дни. Существуют методы классов deflate и inflate, которые допускают быстрые переходы, подобные этим:

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

Я думаю, что это отвечает на вопрос "Как мне распаковать строку?" лучшее. :)

3 голосов
/ 18 октября 2011

Чтобы скопировать содержимое, используйте следующий код (проверено на 1.9.2)

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

Остерегайтесь проблем с кодированием

2 голосов
/ 31 марта 2011

Я использовал ответ выше, чтобы использовать Zlib :: Deflate

Я продолжал получать испорченные файлы (для маленьких файлов), и потребовалось много часов, чтобы выяснить, что проблема может быть исправлена ​​с помощью:

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

без линии zstream.finish!

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