2009-09-01 43 views
42

Zlib :: GzipReader có thể lấy "đối tượng IO hoặc IO". vì nó là đầu vào, như đã nêu trong tài liệu.Làm thế nào để giải nén chuỗi Gzip trong 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 

Tôi nên giải nén chuỗi như thế nào?

Trả lời

105

Các phương pháp trên không làm việc cho tôi.
Tôi đã gặp lỗi incorrect header check (Zlib::DataError). Rõ ràng nó giả định bạn có một tiêu đề theo mặc định, mà có thể không phải lúc nào cũng đúng.

Công việc xung quanh mà tôi thực hiện là:

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

Cảm ơn bạn, tôi đã nhận được cùng một lỗi và điều này đã giải quyết được vấn đề của tôi! –

+0

Mucho giúp đỡ ở đây quá – simonmorley

+0

đang gọi body.to_s dự phòng? – Blaskovicz

15

Bạn cần Zlib::Inflate cho giải nén của một chuỗi và Zlib :: Deflate cho nén

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

Zlib bởi asumes mặc định rằng dữ liệu nén của bạn có chứa một tiêu đề. Nếu dữ liệu của bạn KHÔNG chứa tiêu đề, nó sẽ thất bại bằng cách tăng Zlib :: DataError.

Bạn có thể nói Zlib đảm nhận các dữ liệu không có tiêu đề thông qua cách giải quyết như sau:

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

Điều này không còn hoạt động. – jm3

5

Sử dụng (-Zlib::MAX_WBITS), tôi đã ERROR: invalid code lengths setERROR: invalid block type
Các chỉ làm việc cho tôi sau, quá.

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

tôi đã sử dụng các câu trả lời trên để sử dụng một Zlib :: Deflate

tôi giữ lấy các file bị hỏng (cho các tập tin nhỏ) và phải mất nhiều giờ để tìm ra rằng vấn đề có thể được cố định bằng:

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

không có dòng zstream.finish!

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

Để gunzip nội dung, sử dụng đoạn mã sau (thử nghiệm trên 1.9.2)

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

Cẩn thận với vấn đề mã hóa

4

Chúng ta không cần bất kỳ thông số thêm những ngày này. Có deflateinflate phương pháp lớp mà cho phép oneliners nhanh chóng như thế này: "Làm thế nào tôi nên ungzip một chuỗi"

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

Tôi nghĩ rằng nó trả lời câu hỏi tốt nhất. :)

+4

Nếu bạn nén và giải nén thì điều này sẽ ổn, nhưng nó sẽ không được nén gzip. Chỉ cần chạy Zlib :: Inflate.inflate (nén) trên dữ liệu nén gzip sẽ giả định nén sai và ném một ngoại lệ "kiểm tra tiêu đề không chính xác". – philwhln

5

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

+1

Đẹp nhất. Từ [tài liệu] (http://www.ruby-doc.org/stdlib-2.1.5/libdoc/zlib/rdoc/Zlib/Inflate.html) "hoặc thêm 16 để chỉ giải mã định dạng gzip (một Zlib: : DataError sẽ được nâng lên cho luồng không phải là gzip) " – iain

4

Trong Rails bạn có thể sử dụng:

  • ActiveSupport::Gzip.compress("my string")
  • ActiveSupport::Gzip.decompress().
Các vấn đề liên quan