How to iterate through an in-memory zip file in Ruby

How to iterate through an in-memory zip file in Ruby

Matts answer is exactly right. Here it is updated to the new 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

And theres no need to monkeypatch StringIO anymore. Progress!

See @bronson’s answer for a more up to date version of this answer using the newer RubyZip API.

The Rubyzip docs you linked to look a bit old. The latest release (0.9.9) can handle IO objects, so you can use a StringIO (with a little tweaking).

Even though the api will accept an IO, it still seems to assumes it’s a file and tries to call path on it, so first monkey patch StringIO to add a path method (it doesn’t need to actually do anything):

require stringio
class StringIO
  def path
  end
end

Then you can do something like:

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

and everything will be done in memory.

How to iterate through an in-memory zip file in Ruby

Zip::File.open_buffer(content) do |zip|
  zip.each do |entry|
    decompressed_data += entry.get_input_stream.read
  end
end

Leave a Reply

Your email address will not be published. Required fields are marked *