lib/io_streams/zip/reader.rb in iostreams-0.20.1 vs lib/io_streams/zip/reader.rb in iostreams-0.20.2
- old
+ new
@@ -1,70 +1,82 @@
module IOStreams
module Zip
class Reader
# Read from a zip file or stream, decompressing the contents as it is read
# The input stream from the first file found in the zip file is passed
- # to the supplied block
+ # to the supplied block.
#
+ # Parameters:
+ # entry_file_name: [String]
+ # Name of the file within the Zip file to read.
+ # Default: Read the first file found in the zip file.
+ #
# Example:
# IOStreams::Zip::Reader.open('abc.zip') do |io_stream|
# # Read 256 bytes at a time
# while data = io_stream.read(256)
# puts data
# end
# end
- def self.open(file_name_or_io, _ = nil, &block)
- if !defined?(JRuby) && !defined?(::Zip)
- # MRI needs Ruby Zip, since it only has native support for GZip
- begin
- require 'zip'
- rescue LoadError => exc
- raise(LoadError, "Install gem 'rubyzip' to read and write Zip files: #{exc.message}")
- end
- end
-
+ def self.open(file_name_or_io, entry_file_name: nil, &block)
# File name supplied
- return read_file(file_name_or_io, &block) unless IOStreams.reader_stream?(file_name_or_io)
+ return read_file(file_name_or_io, entry_file_name, &block) unless IOStreams.reader_stream?(file_name_or_io)
- # ZIP can only work against a file, not a stream, so create temp file.
+ # Ruby ZIP gem uses `#seek` so can only work against a file, not a stream, so create temp file.
+ # JRuby ZIP requires an InputStream.
IOStreams::File::Path.temp_file_name('iostreams_zip') do |temp_file_name|
IOStreams.copy(file_name_or_io, temp_file_name, target_options: {streams: []})
- read_file(temp_file_name, &block)
+ read_file(temp_file_name, entry_file_name, &block)
end
end
if defined?(JRuby)
# Java has built-in support for Zip files
- def self.read_file(file_name, &block)
+ def self.read_file(file_name, entry_file_name)
fin = Java::JavaIo::FileInputStream.new(file_name)
zin = Java::JavaUtilZip::ZipInputStream.new(fin)
- zin.get_next_entry
- block.call(zin.to_io)
+
+ get_entry(zin, entry_file_name) ||
+ raise(Java::JavaUtilZip::ZipException.new("File #{entry_file_name} not found within zip file."))
+
+ yield(zin.to_io)
ensure
zin.close if zin
fin.close if fin
end
else
-
# Read from a zip file or stream, decompressing the contents as it is read
# The input stream from the first file found in the zip file is passed
# to the supplied block
- def self.read_file(file_name, &block)
- begin
- zin = ::Zip::InputStream.new(file_name)
- zin.get_next_entry
- block.call(zin)
- ensure
+ def self.read_file(file_name, entry_file_name)
+ if !defined?(::Zip)
+ # MRI needs Ruby Zip, since it only has native support for GZip
begin
- zin.close if zin
- rescue IOError
- # Ignore file already closed errors since Zip::InputStream
- # does not have a #closed? method
+ require 'zip'
+ rescue LoadError => exc
+ raise(LoadError, "Install gem 'rubyzip' to read and write Zip files: #{exc.message}")
end
end
+
+ ::Zip::InputStream.open(file_name) do |zin|
+ get_entry(zin, entry_file_name) ||
+ raise(::Zip::EntryNameError, "File #{entry_file_name} not found within zip file.")
+ yield(zin)
+ end
end
+ end
+ def self.get_entry(zin, entry_file_name)
+ if entry_file_name.nil?
+ zin.get_next_entry
+ return true
+ end
+
+ while entry = zin.get_next_entry
+ return true if entry.name == entry_file_name
+ end
+ false
end
end
end
end