如何在Ruby中迭代内存中的zip文件

gar*_*tor 11 ruby zip in-memory rack-test

我正在编写一个单元测试,其中一个正在返回一个zip文件,我想检查这个zip文件的内容,从中获取一些值,并将值传递给下一个测试.

我正在使用Rack Test,所以我知道我的zip文件的内容在里面last_response.body.我查看了RubyZip的文档,但似乎总是期待一个文件.由于我正在运行单元测试,我更喜欢在内存中完成所有操作,以免污染任何带有测试zip文件的文件夹,如果可能的话.

bro*_*son 16

马特的答案是完全正确的.在这里它更新为新的API:

Zip::InputStream.open(StringIO.new(input)) do |io|
  while entry = io.get_next_entry
    if entry.name == 'doc.kml'
      parse_kml(io.read)
    else
      raise "unknown entry in kmz file: #{entry.name}"
    end
  end
end
Run Code Online (Sandbox Code Playgroud)

并且不再需要monkeypatch StringIO.进展!


mat*_*att 6

请参阅@bronson的答案,了解使用较新的RubyZip API获取此答案的最新版本.

您链接的Rubyzip文档看起来有点旧.在最新的版本(0.9.9)可以处理IO的对象,所以你可以使用StringIO的(稍加调整).

即使api会接受一个IO,它似乎仍然认为它是一个文件并试图调用path它,所以第一个猴子补丁StringIO添加一个path方法(它不需要实际做任何事情):

require 'stringio'
class StringIO
  def path
  end
end
Run Code Online (Sandbox Code Playgroud)

然后你可以这样做:

require 'zip/zip'
Zip::ZipInputStream.open_buffer(StringIO.new(last_response.body)) do |io|
  while (entry = io.get_next_entry)
    # deal with your zip contents here, e.g.
    puts "Contents of #{entry.name}: '#{io.read}'"
  end
end
Run Code Online (Sandbox Code Playgroud)

一切都将在记忆中完成.


小智 6

Zip::File.open_buffer(content) do |zip|
  zip.each do |entry|
    decompressed_data += entry.get_input_stream.read
  end
end
Run Code Online (Sandbox Code Playgroud)

  • 一些解释可以大大促进理解,而不是复制粘贴,继续前进。 (2认同)