Bye Bye Moore

猫マンション建築の野望を胸に零細事業主として資本主義の荒波に漕ぎ出したアラサー男の技術メモ

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