Zip Extraction Bug?

(ded) #1

I am trying to unzip a zip file with this:

            require 'zip/zip'

            zf = Zip::ZipFile.new(zip_name)
            zf.each do |ent|
                File.delete(ent.name) if test(?f, ent.name)
                zf.extract(ent, ent.name)
            end

I get the following error message, which appears to be a library error:

NameError: uninitialized constant Zip::Decompressor::CHUNK_SIZE
    /usr/lib/ruby/site_ruby/1.8/zip/zip.rb:201:in
`internal_produce_input'
    /usr/lib/ruby/site_ruby/1.8/zip/zip.rb:178:in `read'
    /usr/lib/ruby/site_ruby/1.8/zip/zip.rb:126:in `read'
    /usr/lib/ruby/site_ruby/1.8/zip/zip.rb:1242:in `write_file'
    /usr/lib/ruby/site_ruby/1.8/zip/zip.rb:1242:in `get_input_stream'
    /usr/lib/ruby/site_ruby/1.8/zip/zip.rb:1242:in `write_file'
    /usr/lib/ruby/site_ruby/1.8/zip/zip.rb:1240:in `open'
    /usr/lib/ruby/site_ruby/1.8/zip/zip.rb:1240:in `write_file'
    /usr/lib/ruby/site_ruby/1.8/zip/zip.rb:1135:in `extract'
    /home/ded/lib/ruby/Section16/Retriever.rb:84:in `get_filings'
    /home/ded/lib/ruby/Section16/Retriever.rb:82:in `each'
    /usr/lib/ruby/site_ruby/1.8/zip/zip.rb:794:in `each'
    /usr/lib/ruby/site_ruby/1.8/zip/zip.rb:937:in `each'
    /home/ded/lib/ruby/Section16/Retriever.rb:82:in `get_filings'
    /home/ded/lib/ruby/Section16/test/TestRetriever.rb:8:in
`test_getfirst'

Am I missing something here?

Thanks

ded

(Thomas Sondergaard) #2

ded wrote:

I am trying to unzip a zip file with this:

            require 'zip/zip'

            zf = Zip::ZipFile.new(zip_name)
            zf.each do |ent|
                File.delete(ent.name) if test(?f, ent.name)
                zf.extract(ent, ent.name)
            end

I get the following error message, which appears to be a library error:

NameError: uninitialized constant Zip::Decompressor::CHUNK_SIZE
    /usr/lib/ruby/site_ruby/1.8/zip/zip.rb:201:in
`internal_produce_input'

[snip]

Am I missing something here?

Yep, a working version of rubyzip. rubyzip-0.5.9 is broken so I have just released rubyzip-0.5.11 that should fix the problem. If the gem is not available from the gems.rubyforge.org repository when you read this, you can get it from http://sourceforge.net/projects/rubyzip.

I apologize for the inconvenience

Thomas

(ded) #3

Wow! What a guy. I would offer to bear your children, but I'm a guy
too.

Thanks, Thomas.

(ded) #4

Thomas,

While you're making a list of Todo for zlib, I thought I would pass
along a couple of other things I noticed. Some of these may just be my
newbitude with respect to the ruby language.

1. "rake test" fails on my system because it assumes that each
directory has a .cvsignore file (which are not part of the
distribution). After doing a "touch .cvsignore" in each of the
installation directories, the problem went away.

2. I used Zip::ZipFile.each to enumerate the entries in the archive,
but in reading the documentation it looks like "foreach" is the
iterator. When I tried that, I got an error saying there was no such
method for the Zip::ZipFile class. There is an "each" but that does
not appear in the documentation.

3. I would have found it really helpful to see an example of iterating
through a zip archive and extracting all the entries. The
documentation appears to lack one for this very common unzip operation.

4. A design issue. I would have thought it natural for "extract" to
default the second argument to "./entry.name" so that in the most
common case, it would not need to be supplied.

5. Another design issue. It would seem more natural to me to make
"extract" a method of the Zip::ZipEntry class, which would defult to
extracting itself into the current directory with the entry name. That
way, an unzip operation would become:

Zip::ZipFile.open("archive.zip").each { |entry|
     entry.extract
}

Extraction now requires an awkward reference to the Zip::ZipFile object
inside the block.

6. The extract method should have a parameter that specifies whether
over-writing an existing file should occur. In my opinion, it should
default to overwriting, but I'll concede that that may be the wrong
choice.

My two cents. Thanks for the great library, and keep up the good work.

Thanks,

Dan Doherty (ded)

P.S. Strip off the -google part of my email address if you want to send
e-mail. I dump all the -google stuff, which is rife with spammers.

(Thomas Sondergaard) #5

ded wrote:

1. "rake test" fails on my system because it assumes that each
directory has a .cvsignore file (which are not part of the
distribution). After doing a "touch .cvsignore" in each of the
installation directories, the problem went away.

Okay, I'll take a look at that. Thanks

2. I used Zip::ZipFile.each to enumerate the entries in the archive,
but in reading the documentation it looks like "foreach" is the
iterator. When I tried that, I got an error saying there was no such
method for the Zip::ZipFile class. There is an "each" but that does
not appear in the documentation.

foreach is a class method, so it is used like this

Zip::ZipFile.foreach("my.zip") { |zf| ... }

Zip::ZipFile#each is inherited from Zip::ZipCentralDirectory. You have to pay attention to notice that ZipFile is a descendant of ZipCentralDirectory, maybe an adjustment of the rdoc stylesheet use for http://rubyzip.sf.net can fix that.

3. I would have found it really helpful to see an example of iterating
through a zip archive and extracting all the entries. The
documentation appears to lack one for this very common unzip operation.

Noted.

4. A design issue. I would have thought it natural for "extract" to
default the second argument to "./entry.name" so that in the most
common case, it would not need to be supplied.

Also noted.

5. Another design issue. It would seem more natural to me to make
"extract" a method of the Zip::ZipEntry class, which would defult to
extracting itself into the current directory with the entry name. That
way, an unzip operation would become:

Zip::ZipFile.open("archive.zip").each { |entry|
     entry.extract
}
Extraction now requires an awkward reference to the Zip::ZipFile object
inside the block.

Good idea.

6. The extract method should have a parameter that specifies whether
over-writing an existing file should occur. In my opinion, it should
default to overwriting, but I'll concede that that may be the wrong
choice.

It already has. ZipFile#extract accepts a block. If the block returns true the destination is overwritten. See ziptest.rb:1403.

Thomas

(ded) #6

Thomas,

Thanks for the comments. After I posted this, it occurred to me that
sourceforge is probably the right place for these, so you'll see them
duplicated there.