Archive::Zip::SimpleUnzip(3)

NAME
Archive::Zip::SimpleUnzip - Read Zip Archives

SYNOPSIS
    use Archive::Zip::SimpleUnzip qw($SimpleUnzipError) ;

    my $z = Archive::Zip::SimpleUnzip->NEW('my.zip')
        or die "Cannot open zip file: $SimpleUnzipError\n" ;

    # How many members in the archive?
    my $members = scalar $z->names();

    # Get the names of all the members in a zip archive
    my @names = $z->names();

    # Test member existence
    if ($z->exists('abc.txt'))
    {
     ...
    }

    # Extract member to filesystem
    $z->extract('member') ;
    $z->extract('member', 'outfile') ;

    # Read the zip comment
    my $comment = $zip->comment();

    # Select a member by name
    my $member = $z->member('abc.txt');
    my $name = $member->name();
    my $content = $member->content();
    my $comment = $member->comment();

    # Iterate through a zip archive
    while (my $member = $z->next)
    {
        print $member->name() . "\n" ;

        $member->extract();
        $member->extract("outfile");
    }

    # Archive::Zip::SimpleUnzip::Member

    # Open a filehandle to read from a zip member
    $fh = $member->open("mydata1.txt");

    # Read blocks of data
    read($fh, $buffer, 1234) ;

    # or a line at a time
    $line = <$fh> ;

    close $fh;

    $z->close();

DESCRIPTION
Archive::Zip::SimpleUnzip is a module that allows reading of Zip archives.

For writing Zip archives, there is a companion module, called Archive::Zip::SimpleZip, that can create Zip archives.

  Features

•   Read zip archive from a file, a filehandle or from an in-memory buffer.

    Note that the code assume that the zip archive is being read from a seekable file/filhandle/buffer.

•   Perl Filehandle interface for reading a zip member.

•   Supports deflate, store, bzip2, Zstandard (Zstd), Xz and lzma compression.

•   Supports Zip64, so can read archves larger than 4Gig and/or have greater than 64K members.

  Constructor
     $z = Archive::Zip::SimpleUnzip->new('myzipfile.zip' [, OPTIONS]) ;
     $z = Archive::Zip::SimpleUnzip->new(\$buffer [, OPTIONS]) ;
     $z = Archive::Zip::SimpleUnzip->new($filehandle [, OPTIONS]) ;

The constructor takes one mandatory parameter along with zero or more optional parameters.

The mandatory parameter controls where the zip archive is read from. This can be any one of the following:

•   Input from a Filename

    When SimpleUnzip is passed a string, it will read the zip archive from the filename stored in the string.

•   Input from a String

    When SimpleUnzip is passed a string reference, like "\$buffer", it will read the in-memory zip archive from that string.

•   Input from a Filehandle

    When SimpleUnzip is passed a filehandle, it will read the zip archive from that filehandle. Note the filehandle must be seekable.

See "Options" for a list of the optional parameters that can be specified when calling the constructor.

  Options

-FilesOnly => 1|0
    When true, ignore members in the zip archive that are directories.

    Enabling this option will change the behaviour of the "names", "next" and "exists" methods.

    Default is false.

  Methods

$buffer = $z->content($member)
    Returns the uncompressed data stored in $member. Returns "undef" if the member does not exist.

$buffer = $z->extract($member [, $outfile])
    Uncompresses the data stored in $member and writes it to the filesystem. By default the filename used is the member name. If the optional parameter $outfile is specified, the payload is written to that file instead.

$string = $z->comment()
    Returns the comment, if any, associated with the zip archive.

$z->exists('name')
    Tests for the existence of member "name" in the zip archive.

$count = $z->names()
@names = $z->names()
    In scalar context returns the number of members in the Zip archive.

    In array context returns a list of the names of the members in the Zip archive.

$z->next()
    Returns the next member from the zip archive as a Archive::Zip::SimpleUnzip::Member object. See "Archive::Zip::SimpleUnzip::Member"

    Standard usage is

        use Archive::Zip::SimpleUnzip qw($SimpleUnzipError) ;

        my $match = 'hello';
        my $zipfile = 'my.zip';

        my $z = Archive::Zip::SimpleUnzip->new($zipfile)
            or die "Cannot open zip file: $SimpleUnzipError\n" ;

        while (my $member = $z->next())
        {
            my $name = $member->name();
            my $fh = $member->open();
            while (<$fh>)
            {
                my $offset =
                print "$name, line $.\n" if /$match/;
            }
        }

$z->close()
    Closes the zip archive.

Archive::Zip::SimpleUnzip::Member
The "next" method from "Archive::Zip::SimpleUnzip" returns a member object of type "Archive::Zip::SimpleUnzip::Member" that has the following methods.

$string = $m->name()
    Returns the name of the member.

$string = $m->comment()
    Returns the member comment.

$data = $m->content()
    Returns the uncompressed content.

$buffer = $z->extract() =item $buffer = $z->extract($outfile])
    Uncompresses the data stored in the current member and writes to the filesystem. By default the filename used is the member name. If the optional parameter $outfile is specified, the payload is written to that file instead.

$fh = $m->open()
    Returns a filehandle that can be used to read the uncompressed content.

$bool = $m->isDirectory()
    Returns true if the member is a directory. Otherwise returns false.

$bool = $m->isFile()
    Returns true if the member is standard file. Otherwise returns false.

Examples

  Print the contents of a Zip member
The code below shows how this module is used to read the contents of the member "abc.txt" from the zip archive "my1.zip".

    use Archive::Zip::SimpleUnzip qw($SimpleUnzipError) ;

    my $z = Archive::Zip::SimpleUnzip->new('my1.zip')
        or die "Cannot open zip file: $SimpleUnzipError\n" ;

    my $name = 'abc.txt';
    if ($z->exists($name))
    {
        print $z->content($name);
    }
    else
    {
        warn "$name not present in my1.zip\n"
    }

  Iterate through a Zip file
    use Archive::Zip::SimpleUnzip qw($SimpleUnzipError) ;

    my $zipfile = 'my.zip';
    my $z = Archive::Zip::SimpleUnzip->new($zipfile)
        or die "Cannot open zip file: $SimpleUnzipError\n" ;

    my $members = $z->names();
    print "Zip file '$zipfile' has $members entries\n";

    while (my $member = $z->next())
    {
        print "$member->name()\n";
    }

  Filehandle interface
Here is a simple grep, that walks through a zip file and prints matching strings present in the compressed payload. The "FilesOnly" option has been included in the call to the constructor to automaticaly skip members that just contain directories.

    use Archive::Zip::SimpleUnzip qw($SimpleUnzipError) ;

    my $match = 'hello';
    my $zipfile = 'my.zip';

    my $z = Archive::Zip::SimpleUnzip->new($zipfile, FilesOnly => 1)
        or die "Cannot open zip file: $SimpleUnzipError\n" ;

    while (my $member = $z->next())
    {
        my $name = $member->name();
        my $fh = $member->open();
        while (<$fh>)
        {
            my $offset =
            print "$name, line $.\n" if /$match/;
        }
    }

  rezip
Another example that uses the filehandle interface. This time the code uses "Archive::Zip::SimpleUnzip" to get a filehandle for each member of a zip archive which it passes to "Archive::Zip::SimpleZip" to recompress.

    use Archive::Zip::SimpleUnzip qw($SimpleUnzipError) ;
    use Archive::Zip::SimpleZip qw($SimpleZipError Z_BEST_COMPRESSION) ;

    my $input  = shift ;
    my $output = shift ;

    my $unzip = Archive::Zip::SimpleUnzip->new($input)
                    or die "Cannot open '$input': $SimpleUnzipError";

    my $zip = Archive::Zip::SimpleZip->new($output, Level => Z_BEST_COMPRESSION)
            or die "Cannot create zip file '$output': $SimpleZipError";

    while (my $member = $unzip->next())
    {
        my $name = $member->name();
        warn "Processing member $name\n"  ;

        my $fh = $member->open();

        $zip->addFileHandle($fh, Name => $name)
                or die "Cannot addFileHandle file '$file': $SimpleZipError\n" ;
    }

Zip File Interoperability
The intention is to be interoperable with zip archives created by other programs, like pkzip or WinZip, but the majority of testing carried out used the Info-Zip zip/unzip <http://www.info-zip.org/> programs running on Linux.

This doesn't necessarily mean that there is no interoperability with other zip programs like pkzip and WinZip - it just means that I haven't tested them. Please report any issues you find.

  Compression Methods Supported
The following compression methods are supported

deflate (8)
    This is the most common compression used in zip archives.

store (0)
    This is used when no compression has been carried out.

bzip2 (12)
    Only if the "IO-Compress-Bzip2" module is available.

lzma (14)
    Only if the "IO-Compress-Lzma" module is available.

Xz (95)
    To read Xz content, the module "IO::Uncompress::UnXz" must be installed.

Zstandard (93)
    To read Zstandard content, the module "IO::Uncompress::UnZstd" must be installed.

  Zip64 Support
This modules supports Zip64, so it can read archves larger than 4Gig and/or have greater than 64K members.

  Limitations
The following features are not currently supported.

•   Compression methods not listed in "Compression Methods Supported"

•   Multi-Volume Archives

•   Encrypted Archives

SUPPORT
General feedback/questions/bug reports should be sent to <https://github.com/pmqs/Archive-Zip-SimpleZip/issues> (preferred) or <https://rt.cpan.org/Public/Dist/Display.html?Name=Archive-Zip-SimpleZip>.

SEE ALSO
Archive::Zip::SimpleZip, Archive::Zip, IO::Compress::Zip, IO::Uncompress::UnZip

AUTHOR
This module was written by Paul Marquess, pmqs@cpan.org.

MODIFICATION HISTORY
See the Changes file.

COPYRIGHT AND LICENSE
Copyright (c) 2018-2024 Paul Marquess. All rights reserved.

This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself.