mattk1 has asked for the wisdom of the Perl Monks concerning the following question:

The code below runs successful, but by unzip I got:
$ unzip k.zip Archive: k.zip warning [k.zip]: 186 extra bytes at beginning or within zipfile (attempting to process anyway) inflating: from_ram.t
The file from_ram does exist, but I have to set chmod 666 to extract it. The other file does not exist. What do I have to do, to get both in one zip with permissions set to 0666? http://search.cpan.org/~pmqs/IO-Compress-2.025/lib/IO/Compress/Zip.pm#Constructor_Options says If you are running a Unix derivative this value defaults to 0666 << 16 But it is set to
---------- 1 user user 7 2010-03-29 08:44 from_ram.t
even I set it explicit. I'am working with Kubuntu 9.10, perl, v5.10.0, IO::Compress::Zip::VERSION 2.024
$ file -ik k.zip k.zip: application/zip; charset=binary
I can open the zip per double click in konqueror without error. But I also see only the one file. A look in the bytecode of the zip shows both filenames. It goes without saying, that I have checked each zip command separate.
#!/usr/bin/perl use strict; use warnings; use IO::Compress::Zip qw(zip $ZipError :constants) ; use diagnostics; my $zip; zip './a.txt' => \$zip, name => 'from_filename.t', AutoClose => 1, BinModeIn => 1 or die "zip failed: $ZipError\n"; my $string = ss(); zip \$string => \$zip, name => 'from_ram.t', ExtAttr => '0666', Append => 1 or die "zip failed: $ZipError\n"; open my $fh, '>','./k.zip' or die "$!"; print $fh $zip; close($fh); sub ss { return <<END; a b c END }
I know Archive::Zip, but it is no core module, and this one is core and seems to do what I need, if I use it right.

Replies are listed 'Best First'.
Re: Build 1 zip from file and string with IO::Compress::Zip
by cdarke (Prior) on Mar 29, 2010 at 13:26 UTC
    The documentation for IO::Compress::Zip marks Append with the Functional Interface as TODO. I tried your example using the OO interface with Append (the doc implies that should work) but got no further. However Multi-Stream seems to work:
    #!/usr/bin/perl use strict; use warnings; use IO::Compress::Zip qw(zip $ZipError :constants); my $z; $z = new IO::Compress::Zip './k.zip', name => 'from_filename.t', AutoClose => 1, BinModeIn => 1 or die "IO::Compress::Zip(1) failed: $ZipError\n"; open (my $fh, '<', './a.txt') or die "Unable to open a.txt: $!"; while (<$fh>) { $z->print ($_) } close $fh; my $string = ss(); $z->newStream( Name => 'from_ram.t', ExtAttr => 0666 << 16) or die "newStream failed: $ZipError\n"; $z->print ($string); close $z; sub ss { return <<END; a b c END }
    Note that I set the permissions in ExtAttr - the default does not appear to be implemented (I got 000 without it), and it is not a string as your code supplies it.
      That's exact what I wanted. Thank you. Curious. A module marked with to do's and not working implementations in core. Hope with Perl 6 comes something better. (-:
        I'm gutted :-)

        Have you tried the sample code posted that used newStream? If it doesn't work, please get back to me.

        Paul

      The Append option isn't what is needed here (the way Append is used in the posted code will result in two zip files concatenated together)

      As you've demonstrated, the MultiStream option is the way to create a single zip file with multiple members.

      Regarding ExtAttr, as you say it is a number, not a string. Plus it isn't being set to "0666<<16" by default as the documentation states -- I will look into that.

      Paul

Re: Build 1 zip from file and string with IO::Compress::Zip
by bart (Canon) on Mar 30, 2010 at 09:12 UTC
    The documentation for that module states:
    The primary purpose of this module is to provide streaming write access to zip files and buffers. It is not a general-purpose file archiver. If that is what you want, check out Archive::Zip.

    I believe that what you want is outside the scope of this module: if you want to create a zip archive with more than one file in it, you should be looking at Archive::Zip.

Re: Build 1 zip from file and string with IO::Compress::Zip
by 7stud (Deacon) on Mar 29, 2010 at 13:00 UTC

    I thought maybe you could write your string to a file, then add both files to a .zip file. However, it doesn't appear that you can compress more than one file in the created .zip file. Try running the examples in the docs--they create a separate .zip file for each input file.

    It's not clear to me what your objective is. Do you want one file containing all the data to be zipped? Or do you want the zip file to contain two files? If you want one file with all the data, first append your string to your file, then zip it.

    The documentation for that module is horrible. I can't believe they let a module into the core without having some minimum standard of documentation.