2013-07-26 29 views
19

Tôi có một ứng dụng web (ruby trên đường ray) sẽ gửi một số YAML làm giá trị của trường nhập ẩn.Nén chuỗi lớn trong ruby ​​

Bây giờ tôi muốn giảm kích thước của văn bản được gửi qua trình duyệt. Dạng nén lossless hiệu quả nhất có thể gửi qua dữ liệu tối thiểu là gì? Tôi ok để chịu thêm chi phí nén và giải nén ở phía máy chủ.

Trả lời

47

Bạn có thể sử dụng việc thực hiện zlib trong lõi ruby ​​để ở/dữ liệu de-Flate:

require "zlib" 
data = "some long yaml string" * 100 
compressed_data = Zlib::Deflate.deflate(data) 
#=> "x\x9C+\xCE\xCFMU\xC8\xC9\xCFKW\xA8L\xCC\xCDQ(.)\xCA\xCCK/\x1E\x15\x1C\x15\x1C\x15\x1C\x15\x1C\x15\x1C\x15\x1C\x15\x1C\x15D\x15\x04\x00\xB3G%\xA6" 

Bạn nên base64 mã hóa các dữ liệu nén để làm cho nó có thể in được:

require 'base64' 
encoded_data = Base64.encode64 compressed_data 
#=> "eJwrzs9NVcjJz0tXqEzMzVEoLinKzEsvHhUcFRwVHBUcFRwVHBUcFUQVBACz\nRyWm\n" 

Sau , ở phía máy khách, bạn có thể sử dụng pako (một cổng zlib để javascript) để lấy lại dữ liệu của bạn. This answer có thể giúp bạn triển khai phần JS.

Để cung cấp cho bạn một ý tưởng về hiệu quả như thế nào đây là, đây là kích thước của chuỗi Ví dụ:

data.size   # 2100 
compressed_data.size # 48 
encoded_data.size # 66 

Cùng một điều đi ngược lại khi nén trên máy khách và lạm phát trên máy chủ.

Zlib::Inflate.inflate(Base64.decode64(encoded_data)) 
#=> "some long yaml stringsome long yaml str ... (shortened, as the string is long :) 

Disclaimer:

  • zlib ruby ​​thực hiện nên phù hợp với việc thực hiện Pako. Nhưng tôi đã không thử nó.
  • Các con số về kích thước chuỗi bị lừa một chút. Zlib thực sự hiệu quả ở đây, bởi vì chuỗi lặp lại rất nhiều. Dữ liệu thực tế thường không lặp lại nhiều.
+2

Đường nối Tôi đã bỏ phiếu này do tai nạn vài ngày trước vì tôi không nhớ là đã làm. Nếu bạn vui lòng, hãy chỉnh sửa để tôi có thể rút lại phiếu bầu tình cờ của mình: ( – Krule

+2

@Krule cảm ơn vì đã tốt đẹp. Trước tiên tôi không chắc liệu tôi có tìm thấy bản cập nhật hữu ích không, nhưng sau đó tôi tình cờ gặp pako (dường như) là một thư viện zlib js tốt hơn nhiều so với zlib. Vì vậy, nhờ lời nhắc xem lại câu trả lời của tôi, tôi có thể cải thiện nó :) – tessi

+4

Xin lưu ý rằng đầu ra của 'Zlib :: Deflate.deflate' không tương thích với định dạng rằng tiện ích dòng lệnh 'gzip' sẽ tạo và sẽ không được' gunzip' chấp nhận, mà dự kiến ​​một số dữ liệu tiêu đề trước nội dung được nén. Nếu bạn muốn đọc đầu ra bằng cách sử dụng 'gunzip', đoạn mã sau sẽ hữu ích:' Zlib :: Deflate.new (nil, 31) .deflate (dữ liệu, Zlib :: FINISH) ' – Guss

Các vấn đề liên quan