d135-1r43
d135-1r43

Reputation: 2485

Trouble storing files with Archive::Zip: I get empty zip files without error code

When I try to create zip archives via Archive::Zip there are no errors thrown, but the resulting zip file is broken.

use Archive::Zip;

my $zip = Archive::Zip->new();
my $file = "/a/very/long/path/with/191/characters/file.txt";

if(-f $file)
{
  $zip->addFile("$file", "destinationname.txt");
  print "$file added\n";
}
unless ($zip->writeToFileNamed("out.zip") == "AZ_OK") { die "error";};

Now my out.zip file is just 22B and is empty:

$> > unzip -l out.zip
Archive:  out.zip
warning [out.zip]:  zipfile is empty

What goes wrong?

First Update: Everything works fine when I use files with a shorter path name. Any idea for a workaround? Symlinking does not work.

Second update: This works as a workaround:

use File::Slurp;
[...]
my $text = read_file($file);
$zip->addString($text, "destinationfile.txt");
[..]

Upvotes: 0

Views: 3189

Answers (3)

frag
frag

Reputation: 1

maybe i have understood what is the problem : you use the full root a/very/long/path/with/191/characters/file.txt

so you compress all directories in you zip, your file is empty because your are note able to see the path. use chdir chdir 'a/very/long/path/with/191/characters/'

Upvotes: 0

Borodin
Borodin

Reputation: 126722

I cannot see why your program creates an empty zip file, but you are misusing quotation marks in several places.

In particular the value AZ_OK is a symbol for a numeric value that you can import by request.

The writeToFileNamed method will never return the string "AZ_OK" and also you should compare strings using eq instead of ==.

Fortunately (or not, depending on your point of view) these two errors together with your failure to import the value of AZ_OK and your omission of use warnings will compare the return value of writeToFileNamed with zero (the proper value of AZ_OK) and should give you the correct results.

Try this program instead.

use strict;
use warnings;

use Archive::Zip qw( :ERROR_CODES );

my $zip = Archive::Zip->new;
my $file = 'a/very/long/path/with/191/characters/file.txt';

if (-f $file) {
  $zip->addFile($file, 'destinationname.txt');
  print "$file added\n";
}

my $status = $zip->writeToFileNamed('out.zip');
$status == AZ_OK or die "error $status";

Update

The length of the path is unlikely to make any difference unless it is hundreds of characters long.

Try this version and tell us what you get.

use strict;
use warnings;

use Archive::Zip qw( :ERROR_CODES );

my $zip = Archive::Zip->new;
my $file = 'a/very/long/path/with/191/characters/file.txt';

unlink 'out.zip';

die qq(File "$file" not found) unless -f $file;
$zip->addFile($file, 'destinationname.txt');
print "$file added\n";

my $status = $zip->writeToFileNamed('out.zip');
$status == AZ_OK or die "error $status";

Upvotes: 0

Oleg V. Volkov
Oleg V. Volkov

Reputation: 22421

Change it to: $zip->addFile($plmxmlFile);.

$zip is already reference to your target file and by adding name of file you'd use for output, you're making Archive::Zip try read and write from same file on assembling attempt, creating a mess (and just generally doing not what your really wanted).

Upvotes: 1

Related Questions