公開日

GZip形式のS3上のファイルをRubyのIO.pipeでストリーム読み出し

やりたいこと

S3からgzip形式のファイルをストリーミングダウンロードしてそれを読み出す。

S3からのダウンロード

公式ドキュメントによるとこうする。

If you want to stream an object from S3, you can pass a block to #read.

File.open('output', 'wb') do |file|
  large_object.read do |chunk|
    file.write(chunk)
  end
end

gzipを読む

gzipの読み出しのサンプルコードはこんな感じ。

File.open('hoge.gz') do |f|
  gz = Zlib::GzipReader.new(f)
  print gz.read
  gz.close
end

via. http://apidock.com/ruby/Zlib/GzipReader

pipeでつなぐ

IO.pipeを使ってつなぐとこう。

IO.pipe do |read_io, write_io|
  write_io.binmode
  thread = Thread.new do
    begin
      AWS::S3::S3Object.read do |chunk|
        write_io.write(chunk)
      end
    rescue
      write_io.close
    end
  end

  gz = Zlib::GzipReader.new(read_io)
  while line = gz.gets
    # do something with line ...
    puts line
  end
end

注意点としては以下。

  1. gzip形式なのでwrite_io.binmodeでバイナリモードにすること
  2. Thread内で何かエラーが起こったときにgetsが待ち状態で止まっちゃうのでcloseなりなんなり適切な処理をしてやること

参考