【问题标题】:How do I get Zlib to uncompress from S3 stream in Ruby?如何让 Zlib 从 Ruby 中的 S3 流中解压缩?
【发布时间】:2014-06-06 07:25:04
【问题描述】:

Ruby Zlib::GzipReader 应该通过一个类似 IO 的对象创建(必须有一个行为与 IO#read 相同的读取方法)。

我的问题是我无法从 AWS::S3 lib 获取这个类似 IO 的对象。 据我所知,获得流的唯一方法是将块传递给S3Object#stream

我已经试过了:

Zlib::GzipReader.new(AWS::S3::S3Object.stream('file', 'bucket'))
# Wich gaves me error: undefined method `read' for #<AWS::S3::S3Object::Value:0x000000017cbe78>

有人知道我该如何实现吗?

【问题讨论】:

    标签: ruby amazon-s3 stream compression


    【解决方案1】:

    一个简单的解决方案是将下载的数据写入StringIO,然后将其读回:

    require 'stringio'
    
    io = StringIO.new
    io.write AWS::S3::S3Object.value('file', 'bucket')
    io.rewind
    
    gz = Zlib::GzipReader.new(io)
    data = gz.read
    gz.close
    
    # do something with data ...
    

    更复杂的方法是在流仍在下载时开始对 gzip 压缩的数据进行膨胀,这可以通过 IO.pipe 来实现。类似这样的东西:

    reader, writer = IO.pipe
    
    fork do
      reader.close
      AWS::S3::S3Object.stream('file', 'bucket') do |chunk|
        writer.write chunk
      end
    end
    
    writer.close
    
    gz = Zlib::GzipReader.new(reader)
    while line = gz.gets
      # do something with line ...
    end
    
    gz.close
    

    您也可以使用Thread 代替fork

    reader, writer = IO.pipe
    
    thread = Thread.new do
      AWS::S3::S3Object.stream('file', 'bucket') do |chunk|
        writer.write chunk
      end
      writer.close
    end
    
    gz = Zlib::GzipReader.new(reader)
    while line = gz.gets
      # do something with line
    end
    
    gz.close
    thread.join
    

    【讨论】:

    • 你的第一个解决方案正是我想出的,但只是作为一种解决方法,因为它一次只做一件事(首先加载到内存中然后读取它)
    • 我没有尝试,因为我正在使用 gz.each_line 并且(如果我错了,请纠正)它不会以这种方式工作
    • 您应该能够将gz.read(CHUNK_SIZE) 替换为gz.gets 以便阅读整行。 ruby-doc.org/core-2.1.2/IO.html#method-i-gets
    • 成功了,谢谢!有什么理由不能与Thread.new 一起使用,而只能与fork 一起使用?
    猜你喜欢
    • 1970-01-01
    • 2011-03-11
    • 2012-11-01
    • 2010-12-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-08-19
    相关资源
    最近更新 更多