Add `File::count_entries`.

This method provides a short cut to finding out how many entries are in
an archive by reading this number directly from the central directory,
and not iterating through the entire set of entries.
This commit is contained in:
Robert Haines 2021-11-20 10:53:00 +00:00
parent 3db1eff1e3
commit 22e47641e6
2 changed files with 32 additions and 0 deletions

View File

@ -171,6 +171,20 @@ module Zip
zip_file.each(&block)
end
end
# Count the entries in a zip archive without reading the whole set of
# entry data into memory.
def count_entries(path_or_io)
cdir = ::Zip::CentralDirectory.new
if path_or_io.kind_of?(String)
::File.open(path_or_io, 'rb') do |f|
cdir.count_entries(f)
end
else
cdir.count_entries(path_or_io)
end
end
end
# Returns an input stream to the specified entry. If a block is passed

View File

@ -186,6 +186,24 @@ class ZipFileTest < MiniTest::Test
Zip::File.open('test/data/max_length_file_comment.zip')
end
def test_count_entries
[
['test/data/osx-archive.zip', 4],
['test/data/zip64-sample.zip', 2],
['test/data/max_length_file_comment.zip', 1]
].each do |filename, num_entries|
assert_equal(num_entries, ::Zip::File.count_entries(filename))
::File.open(filename, 'rb') do |f|
assert_equal(num_entries, ::Zip::File.count_entries(f))
f.seek(0)
s = StringIO.new(f.read)
assert_equal(num_entries, ::Zip::File.count_entries(s))
end
end
end
def test_cleans_up_tempfiles_after_close
zf = ::Zip::File.new(EMPTY_FILENAME, create: true)
zf.get_output_stream('myFile') do |os|