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

Gurus: I'm loosing my mind trying to figure the below issue out. I am trying to archive some XML, but when I get the following error: read error at C:\Perl\zipscript.pl line 90.
#!/usr/bin/perl -w use strict; use warnings; use File::Basename; use Archive::Zip qw( :ERROR_CODES :CONSTANTS ); my $procdate = sprintf "%02d%02d%02d%02d%02d%02d", (localtime)[4]+1, ( +localtime)[3], substr((localtime)[5]+1900,2,2),(localtime)[2], (local +time)[1], (localtime)[0]; #Pull in all the xml files for each report. my @dipfile = glob('C:/ReportExtract/Director/*.xml'); foreach my $xml_file (@dipfile) { ##### Zip each file into a zip file for archiving ##### my $targetdir = File::Spec->catdir('C:/ReportExtract/Director/'); my $targetzip = File::Spec->catdir($targetdir, basename($procd +ate) . ".zip"); #Need basename. my $zip = Archive::Zip->new(); my $zipdir = $zip->addDirectory($targetdir); my $temp = File::Basename::fileparse($xml_file); $zipdir = $zip->addFile('test.xml'); #$zip->writeToFileNamed($targetzip); unless ( $zip->writeToFileNamed($targetzip) eq "AZ_OK" ) { die 'read error';} };
Your help would be greatly appreciated. Thanks, Dave

Replies are listed 'Best First'.
Re: Archive::Zip Simple Issue
by Fletch (Bishop) on May 29, 2009 at 18:52 UTC

    One immediately wonders how a just under 30 line script could produce an error on line 90 . . .

    Update: And tangentially you've re-implemented strftime unnecessarily.

    Update 2: And I just noticed that you're comparing the return code using string-equality against strings rather than checking for numeric equality against the constants exported from the module. That kinda makes a difference as well.

    The cake is a lie.
    The cake is a lie.
    The cake is a lie.

Re: Archive::Zip Simple Issue
by scorpio17 (Canon) on May 29, 2009 at 19:35 UTC

    By putting "my $zip = Archive::Zip->new();" inside the loop, you're creating a new archive for each file. You need to create one archive, outside of the loop, then loop over the files, adding each one to the archive.

      I tried putting it outside and it seems to get that same error message. I creates each zip file, but the zip file is empty.
      #!/usr/bin/perl -w use strict; use warnings; use File::Basename; use Archive::Zip qw( :ERROR_CODES :CONSTANTS ); my $procdate = sprintf "%02d%02d%02d%02d%02d%02d", (localtime)[4]+1, ( +localtime)[3], substr((localtime)[5]+1900,2,2),(localtime)[2], (local +time)[1], (localtime)[0]; my @dipfile = glob('C:/ReportExtract/Director/*.xml'); ##### Zip each file into a zip file for archiving ##### my $targetdir = File::Spec->catdir('C:/ReportExtract/Director/'); my $targetzip = File::Spec->catdir($targetdir, basename($procdate) . " +.zip"); #Need basename. my $zip = Archive::Zip->new(); my $zipdir = $zip->addDirectory($targetdir); foreach my $xml_file (@dipfile) { my $temp = File::Basename::fileparse($xml_file); #Trying it with o +nly the basename. $zipdir = $zip->addFile($temp); }; unless ( $zip->writeToFileNamed($targetzip) eq "AZ_OK" ) {die 'rea +d error';}
      Here is the updated code. Dave

        I think $zip->addFile() needs the complete path, not just the filename. So try this:

        # outside of loop: $dir = "C:/ReportExtract/Director"; # ... # inside your foreach loop: if (-e "$dir/$temp" ) { unless ( $zip->addFile("$dir/$temp") ) { print "Error: failed to add $dir/$temp to archive.\n"; } } else { print "Error: $dir/$temp does not exist!\n"; }

        This also adds error checking, so you can see if it's doing the right thing as it runs.