0

I'm trying to read the content of a file (a.txt) that I just created. This file contains a string consisting of "ABCDE", which I then tar with the write() function. I can see that the "a.tar" is created in my directory, but when I come up to the read() function, I get an error : Can't read a.tar : at testtar.pl line 14.

Am I doing something wrong ? Is it because I am on Windows ?

use strict;
use warnings;
use Archive::Tar;
# $Archive::Tar::DO_NOT_USE_PREFIX = 1;

my $tari = Archive::Tar->new();
$tari->add_files("a.txt");
$tari->write("a.tar");

my $file = "a.tar";

my $tar = Archive::Tar->new() or die "Can't create a tar object : $!";
if(my $error = $tar->read($file)) {
    die "Can't read $file : $!";
}

my @files = $tar->get_files();
for my $file_obj(@files) {
my $fh = $file_obj->get_content();
binmode($fh);
my $fileName = $file_obj->full_path();
my $date = $file_obj->mtime();
print $fh;
}

Thanks.

Jonathan Taws
  • 1,168
  • 11
  • 24

2 Answers2

3

You misunderstand the return value of read of Archive::Tar:

$tar->read ( $filename|$handle, [$compressed, {opt => 'val'}] )

Returns the number of files read in scalar context, and a list of Archive::Tar::File objects in list context.

Please change the following

if(my $error = $tar->read($file)) {
    die "Can't read $file : $!";
}

to

unless ($tar->read($file)) {
    die "Can't read $file : $!";
}

and try again.

Community
  • 1
  • 1
Lee Duhem
  • 14,695
  • 3
  • 29
  • 47
  • Okay, so it is now working with your correction. Could you please explain why mine was incorrect ? Was it because read was "reading" one file and evaluated to true, thus going into the die statement ? – Jonathan Taws May 15 '14 at 12:25
  • @Hawknight `read` returns 1 to indicate there is one file in `a.tar`, and you use that return value as condition, which will be interpreted as true by `if` statement, so that `die` will run. – Lee Duhem May 15 '14 at 14:53
  • Ok, I understand now. I copy/pasted the methods from Archive::Zip to Archive::Tar, and some don't work the same way. Thanks for the answer ! – Jonathan Taws May 15 '14 at 15:01
1

This is wrong:

my $fh = $file_obj->get_content();
binmode($fh);

get_content() gives you the contents of the file and not a filehandle. binmode() is expecting a filehandle. Also, you can use !defined instead of unless (I think it's easier to read).

Rewritten below:

#!/bin/env perl
use strict;
use warnings;
use Archive::Tar;

my $tari = Archive::Tar->new();
$tari->add_files("a.txt");
$tari->add_files("b.txt");
$tari->add_files("c.txt");
$tari->add_files("d.txt");
$tari->write("a.tar");

my $file = "a.tar";

my $tar = Archive::Tar->new() or die "Can't create a tar object : $!";
if(!defined($tar->read($file)))
{
    die "Can't read $file : $!";
}

my @files = $tar->get_files();
for my $file_obj(@files)
{
    my $fileContents = $file_obj->get_content();
    my $fileName = $file_obj->full_path();
    my $date = $file_obj->mtime();
    print "Filename: $fileName Datestamp: $date\n";
    print "File contents: $fileContents";
    print "-------------------\n";
}
ktang
  • 349
  • 2
  • 10
  • Thanks for the advice ! I get a warning message if I keep the binmode anyways :) I must admit it's easier to read !defined than unless, good insight – Jonathan Taws May 15 '14 at 12:29