Bye Bye Moore

PoCソルジャーな零細事業主が作業メモを残すブログ

Zlib::GzipReader/WriterとStringIOをつかってファイルを作らずGzip圧縮なデータを扱う

ZlibはRubyに標準添付さえている圧縮系ライブラリです。
普段はFileクラスと一緒に使ったりします。
これとStringIOと組み合わせると、ネットワーク上でも利用可能です。

実際のところ。

str = ""; (0..1000).each { str += (0x61 + rand(0x10)).chr }
0..1000
> str
#"koij ... ame"
str.size
#1001

data = Zlib::Deflate.deflate(str)
#"x\x9C\x1D\x93I ... \xF5\x82\xE4\x1F\e\xDF\x98\a"
data.size
#561

また、Gzip自体をそのまんま扱う事もできます。
これとStringIOを組み合わせる事で、関数内で圧縮して外出す……といった挙動の関数が実装可能です。

def compress(str)
  stream = StringIO.new("w")
  Zlib::GzipWriter.new(stream) {|w| w.write(str) }
  #>> "\u001F\x8B\b\u ... {$\e\xB7\xE9\u0003\u0000\u0000"

  stream.string
end

読み出しも同様に可能です

      def decompress(data, raw_data)
        begin
          input = StringIO.new(data, "r")
          reader = Zlib::GzipReader.new(input)
          reader.read
        rescue Zlib::GzipFile::Error => gze
          raise FlexColumns::Errors::InvalidCompressedDataInDatabaseError.new(data_source, raw_data, gze)
        end
      end