IO::COMPRESS::ZIP(3perl)
โจ NAME โจ
IO::Compress::Zip โ bestie, it writes zip files and zip buffers ๐
(this is the perl manual page, 3perl, if you're keeping track)
๐ SYNOPSIS ๐
okay so here's the vibe, literally copy-paste this energy:
use IO::Compress::Zip qw(zip $ZipError) ;
my $status = zip $input => $output [,OPTS]
or die "zip failed: $ZipError\n";
my $z = IO::Compress::Zip->new( $output [,OPTS] )
or die "zip failed: $ZipError\n";
$z->print($string);
$z->printf($format, $string);
$z->write($string);
$z->syswrite($string [, $length, $offset]);
$z->flush();
$z->tell();
$z->eof();
$z->seek($position, $whence);
$z->binmode();
$z->fileno();
$z->opened();
$z->autoflush();
$z->input_line_number();
$z->newStream( [OPTS] );
$z->deflateParams();
$z->close() ;
$ZipError ;
# IO::File mode
print $z $string;
printf $z $format, $string;
tell $z
eof $z
seek $z, $position, $whence
binmode $z
fileno $z
close $z ;
likeโฆ it's giving "so many methods, so little time" ๐ธ
๐ DESCRIPTION ๐
This module hands you a Perl interface that lets you write zip compressed data to files or to buffers. Two destinations, one icon โจ
The whole main character purpose here? streaming write access to zip files and buffers. Stream it, don't hoard it ๐
So at present, the following compression methods are supported by IO::Compress::Zip:
- Store (0) โ the no-thoughts-just-vibes option ๐
- Deflate (8) โ the classic, she ate ๐
- Bzip2 (12) โ lowkey a whole extra dependency, see below
- To write Bzip2 content, the module
IO::Uncompress::Bunzip2must be installed. not me needing a whole other module just to write it ๐ญ
- To write Bzip2 content, the module
- Lzma (14) โ same rules apply
- To write LZMA content, the module
IO::Uncompress::UnLzmamust be installed.
- To write LZMA content, the module
- Zstandard (93) โ the fancy new girl ๐ฅ
- To write Zstandard content, the module
IO::Compress::Zstdmust be installed.
- To write Zstandard content, the module
- Xz (95) โ yes bestie, xz is here too
- To write Xz content, the module
IO::Uncompress::UnXzmust be installed.
- To write Xz content, the module
fr fr, every single one of those fancy compression methods comes with a "you gotta install this other module first" condition. no cap, check before you ship ๐
And if you're trying to read zip files/buffers instead? That's a different queen entirely โ go see the companion module IO::Uncompress::Unzip ๐ฆ
part 1 of 5 โ there's SO much more coming bestie, stay with me ๐ซถ
โจ Functional Interface โจ
Okay bestie, so there's a top-level function called zip that does the whole "one-shot" compression thing between buffers and/or files ๐. If you want finer control over the compression process, go peek at the "OO Interface" section instead, ok?
use IO::Compress::Zip qw(zip $ZipError) ;
zip $input_filename_or_reference => $output_filename_or_reference [,OPTS]
or die "zip failed: $ZipError\n";
Heads up ๐ซถ โ the functional interface needs Perl5.005 or better.
๐ธ zip $input_filename_or_reference => $output_filename_or_reference [, OPTS] ๐ธ
zip wants at least two parameters โ $input_filename_or_reference and $output_filename_or_reference โ plus zero or more optional ones (those live in "Optional Parameters", keep scrolling bestie).
๐ The $input_filename_or_reference parameter
This param defines where your uncompressed data is coming from. It can be one of these forms:
- A filename โ if
$input_filename_or_referenceis a simple scalar, it's treated as a filename ๐ . The file gets opened for reading and the input data gets read from it. - A filehandle โ if it's a filehandle, the input data is read from it. The string
'-'works as an alias for standard input ๐. - A scalar reference โ if it's a scalar reference, the input data is read from
$$input_filename_or_reference. - An array reference โ if it's an array reference, every element in the array has to be a filename โจ. The input data gets read from each file in turn. The complete array gets walked first to make sure it only holds valid filenames before any data gets compressed โ safety first, no cap.
- An Input FileGlob string โ if
$input_filename_or_referenceis a string wrapped in the characters"<"and">",zipassumes it's an input fileglob string ๐ฆ. The input is the list of files matching that fileglob. SeeFile::GlobMapperfor more deets.
If $input_filename_or_reference is any other type, "undef" gets returned ๐ญ.
On top of that, if $input_filename_or_reference points at a filename on the filesystem, a bunch of zip file header fields get populated by default using these attributes from the input file ๐
- the full filename contained in
$input_filename_or_reference - the file protection attributes
- the UID/GID for the file
- the file timestamps
If you're not vibing with those defaults, you can override them by explicitly setting one or more of the "Name", "Time", "TextFlag", "ExtAttr", "exUnixN" and "exTime" options โ or by setting the "Minimal" parameter ๐.
๐ The $output_filename_or_reference parameter
This one controls where the compressed data actually goes. It can take one of these forms:
- A filename โ if
$output_filename_or_referenceis a simple scalar, it's assumed to be a filename ๐ . It gets opened for writing, and the compressed data goes in there. - A filehandle โ if it's a filehandle, the compressed data gets written to it. The string
'-'is an alias for standard output ๐. - A scalar reference โ if it's a scalar reference, the compressed data lands in
$$output_filename_or_reference. - An Array Reference โ if it's an array reference, the compressed data gets pushed onto the array โจ.
- An Output FileGlob โ if it's a string delimited by the characters
"<"and">",zipassumes it's an output fileglob string ๐ฆ. The output is the list of files matching the fileglob. > โ ๏ธ When$output_filename_or_referenceis a fileglob string,$input_filename_or_referencemust also be a fileglob string. Anything else is an error, periodt. SeeFile::GlobMapperfor more details.
If $output_filename_or_reference is any other type, "undef" gets returned ๐ญ.
๐ Notes ๐
When $input_filename_or_reference maps to multiple files/buffers and $output_filename_or_reference is a single file/buffer, each of those input files/buffers gets stored in $output_filename_or_reference as its very own distinct entry ๐. One archive, many little entries, it's giving organized.
๐ Optional Parameters ๐
The optional params for the one-shot zip are (mostly) identical to the ones used with the OO interface over in "Constructor Options". The exceptions are the ones listed right here, bestie:
"AutoClose => 0|1"โ This applies to any input or output data streams you hand tozipthat are filehandles. If"AutoClose"is specified and true, it'll close all the input and/or output filehandles onceziphas finished ๐ธ. Defaults to0."BinModeIn => 0|1"โ This option is now a no-op ๐. All files get read in binmode."Append => 0|1"โ What this does depends on the type of output data stream:- A Buffer โ if
"Append"is enabled, all compressed data gets appended to the end of the output buffer. Otherwise the output buffer gets cleared before any compressed data is written to it. - A Filename โ if
"Append"is enabled, the file opens in append mode. Otherwise the file's contents (if any) get truncated before any compressed data is written. - A Filehandle โ if
"Append"is enabled, the filehandle gets positioned at the end of the file via a call to"seek"before any compressed data is written. Otherwise the file pointer does not move, nope.
- A Buffer โ if
When "Append" is specified and true, it appends all compressed data to the output data stream ๐. So: output is a filehandle โ it does a seek to the eof before writing anything. Output is a filename โ it opens for appending. Output is a buffer โ all compressed data gets appended onto the existing buffer. Slay.
Conversely, when "Append" isn't specified, or it's present and false, here's the vibe: output is a filename โ it truncates the file's contents before writing any compressed data. Output is a filehandle โ its position doesn't change. Output is a buffer โ it gets wiped before any compressed data is output ๐งน.
Defaults to 0.
๐ฆ Oneshot Examples ๐ฆ
A few examples so you can see what this module can do, bestie.
Streaming
This very simple command line example flexes the module's streaming capabilities โจ. The code reads data from STDIN, compresses it, and writes the compressed data to STDOUT.
$ echo hello world | perl -MIO::Compress::Zip=zip -e 'zip \*STDIN => \*STDOUT' >output.zip
The special filename "-" can stand in for both "\*STDIN" and "\*STDOUT", so the above can be rewritten as ๐
$ echo hello world | perl -MIO::Compress::Zip=zip -e 'zip "-" => "-"' >output.zip
One problem with creating a zip archive straight from STDIN can be shown by peeking at the contents of the zip file, output.zip, that we just made:
$ unzip -l output.zip
Archive: output.zip
Length Date Time Name
--------- ---------- ----- ----
12 2019-08-16 22:21
--------- -------
12 1 file
The archive member (filename) used is the empty string ๐.
If that doesn't suit your needs, you can explicitly set the filename used in the zip archive by specifying the Name option, like so:
echo hello world | perl -MIO::Compress::Zip=zip -e 'zip "-" => "-", Name => "hello.txt"' >output.zip
Now the contents of the zip file look like this ๐ :
$ unzip -l output.zip
Archive: output.zip
Length Date Time Name
--------- ---------- ----- ----
12 2019-08-16 22:22 hello.txt
--------- -------
12 1 file
Compressing a file from the filesystem
To read the contents of the file "file1.txt" and write the compressed data to the file "file1.txt.zip" ๐:
use strict ;
use warnings ;
use IO::Compress::Zip qw(zip $ZipError) ;
my $input = "file1.txt";
zip $input => "$input.zip"
or die "zip failed: $ZipError\n";
Reading from a Filehandle and writing to an in-memory buffer
To read from an existing Perl filehandle, $input, and write the compressed data to a buffer, $buffer ๐ธ:
use strict ;
use warnings ;
use IO::Compress::Zip qw(zip $ZipError) ;
use IO::File ;
my $input = IO::File->new( "<file1.txt" )
or die "Cannot open 'file1.txt': $!\n" ;
my $buffer ;
zip $input => \$buffer
or die "zip failed: $ZipError\n";
Compressing multiple files
To create a zip file, "output.zip", containing the compressed contents of the files "alpha.txt" and "beta.txt" ๐:
use strict ;
use warnings ;
use IO::Compress::Zip qw(zip $ZipError) ;
zip [ 'alpha.txt', 'beta.txt' ] => 'output.zip'
or die "zip failed: $ZipError\n";
Or, instead of naming every single file you want to compress by hand, you could use a fileglob to grab all the "txt" files in the current directory, like this โจ:
use strict ;
use warnings ;
use IO::Compress::Zip qw(zip $ZipError) ;
my @files = <*.txt>;
zip \@files => 'output.zip'
or die "zip failed: $ZipError\n";
or, more succinctly ๐ฆ:
zip [ <*.txt> ] => 'output.zip'
or die "zip failed: $ZipError\n";
๐ OO Interface ๐
๐ Constructor ๐
The format of the constructor for IO::Compress::Zip is shown below, bestie:
my $z = IO::Compress::Zip->new( $output [,OPTS] )
or die "IO::Compress::Zip failed: $ZipError\n";
The constructor takes one mandatory parameter, $output (defined below), plus zero or more "OPTS", defined in "Constructor Options" ๐.
It returns an "IO::Compress::Zip" object on success and "undef" on failure ๐ญ. On failure, the variable $ZipError will hold an error message.
Okay so if you're running Perl 5.005 or better (and bestie, you are ๐
), the object $z that IO::Compress::Zip hands back can be used exactly like an IO::File filehandle. Which means every single normal output file operation works on $z. Want to write to a compressed file/buffer? Two ways, both iconic:
$z->print("hello world\n");
print $z "hello world\n";
Here's a lil' baby example of using the OO interface to create an output file myfile.zip and yeet some data into it:
my $filename = "myfile.zip";
my $z = IO::Compress::Zip->new($filename)
or die "IO::Compress::Zip failed: $ZipError\n";
$z->print("abcde");
$z->close();
Want more? Go peek at Examples. ๐ซถ
The mandatory parameter $output is the main character here โ it controls where your compressed data ends up. It can take one of these forms:
- A filename โ if
$outputis a plain ol' scalar, it's assumed to be a filename. That file gets opened for writing and the compressed data goes in it. โจ - A filehandle โ if
$outputis a filehandle, the compressed data is written to it. The string-is a valid alias for standard output. ๐ - A scalar reference โ if
$outputis a scalar reference, the compressed data gets stored in$$output.
If $output is literally any other type, IO::Compress::Zip::new will return undef. Not a vibe, but that's the rules. ๐
โจ Constructor Options โจ
OPTS is any combination of zero or more of the following options:
AutoClose => 0|1โ this one is only valid when$outputis a filehandle. If you set it (and the value is true),$outputgets closed once either theclosemethod is called or theIO::Compress::Zipobject gets destroyed. ๐ธ Defaults to0.Append => 0|1โ opens$outputin append mode. What that actually does depends on what$outputis:- A Buffer
If $output is a buffer and Append is enabled, all compressed data gets appended to the end of $output. Otherwise $output gets cleared out before any data is written to it.
- A Filename
If $output is a filename and Append is enabled, the file is opened in append mode. Otherwise the contents of the file (if it has any) get truncated before any compressed data is written to it.
- A Filehandle
If $output is a filehandle, the file pointer gets positioned to the end of the file via a call to seek before any compressed data is written to it. Otherwise the file pointer does not move.
This parameter defaults to 0.
๐๏ธ File Naming Options ๐๏ธ
Quick zip terminology moment bestie โ a zip archive is made of one or more archive members, and each member has its own filename, known as the archive member name. ๐
The options in this section control how that archive member name (a.k.a. the filename) gets stored in the zip archive.
Name => $stringโ this sets the archive member name in the zip archive explicitly to$string. Most of the time you do not need this option. By default, when you add a filename to a zip archive, the archive member name will match the filename. ๐
You should only reach for this if you want the archive member name to be different from the uncompressed filename, or when the input is a filehandle or a buffer.
The default behaviour for which archive member name gets used when Name isn't specified depends on the form of the $input parameter:
- If
$inputis a filename, the value of$inputis used for the archive member name. - If
$inputis not a filename, the archive member name will be an empty string.
Note that both the CanonicalName and FilterName options can modify the value used for the archive member name. ๐
Also note that you should set the Efs option to true if you're working with UTF8 filenames.
CanonicalName => 0|1โ controls whether the archive member name gets normalized into Unix format before being written to the zip file. Highly recommend you enable this unless you really need to create a non-standard Zip file. ๐
Here's what APPNOTE.TXT has to say about what should be stored in the zip filename header field:
The name of the file, with optional relative path.
The path stored should not contain a drive or
device letter, or a leading slash. All slashes
should be forward slashes '/' as opposed to
backwards slashes '\' for compatibility with Amiga
and UNIX file systems etc.
This option defaults to false.
FilterName => sub { ... }โ this one lets the archive member name get modified before it's written to the zip file. ๐
It takes a parameter that must be a reference to a sub. On entry to the sub, the $_ variable contains the name to be filtered. If no filename is available, $_ contains an empty string.
Whatever $_ is when the sub returns becomes the archive member name.
Note that if CanonicalName is enabled, a normalized filename gets passed to the sub.
If you use FilterName to modify the filename, it's your responsibility to keep that filename in Unix format. No pressure bestie. ๐
Although this option works with the OO interface, it's most useful with the one-shot interface. For example, this code shows how FilterName can strip the path component off a series of filenames before they get stored in $zipfile:
sub compressTxtFiles
{
my $zipfile = shift ;
my $dir = shift ;
zip [ <$dir/*.txt> ] => $zipfile,
FilterName => sub { s[^$dir/][] } ;
}
Efs => 0|1โ controls setting of the "Language Encoding Flag" (EFS) in the zip archive. When it's set, the filename and comment fields for the zip archive MUST be valid UTF-8. ๐ฆ
If the string used for the filename and/or comment isn't valid UTF-8 while this option is true, the script will die with a "wide character" error. ๐ญ
Note that this option only works with Perl 5.8.4 or better.
This option defaults to false.
๐ฆ Overall Zip Archive Structure ๐ฆ
Minimal => 1|0โ if specified, this option disables the creation of all extra fields in the zip local and central headers. So theexTime,exUnix2,exUnixN,ExtraFieldLocalandExtraFieldCentraloptions all get ignored. โจ
This parameter defaults to 0.
Stream => 0|1โ controls whether the zip file/buffer output is created in streaming mode. ๐
Note that when outputting to a file with streaming mode disabled (Stream is 0), the output file must be seekable.
The default is 1.
Zip64 => 0|1โ create a Zip64 zip file/buffer. Use this if you want to store files larger than 4 Gig or store more than 64K files in a single zip archive. ๐
Zip64 will be automatically set, as needed, when working with the one-shot interface when the input is either a filename or a scalar reference.
If you intend to manipulate the Zip64 zip files created with this module using an external zip/unzip, make sure that it supports Zip64.
In particular, if you're using Info-Zip you need to have zip version 3.x or better to update a Zip64 archive, and unzip version 6.x to read a zip64 archive.
The default is 0.
๐๏ธ Deflate Compression Options ๐๏ธ
-Levelโ defines the compression level used by zlib. The value should either be a number between 0 and 9 (0means no compression and9is maximum compression), or one of the symbolic constants defined below.
Z_NO_COMPRESSION
Z_BEST_SPEED
Z_BEST_COMPRESSION
Z_DEFAULT_COMPRESSION
The default is Z_DEFAULT_COMPRESSION.
Note, these constants are not imported by IO::Compress::Zip by default. ๐
use IO::Compress::Zip qw(:strategy);
use IO::Compress::Zip qw(:constants);
use IO::Compress::Zip qw(:all);
-Strategyโ defines the strategy used to tune the compression. Use one of the symbolic constants defined below.
Z_FILTERED
Z_HUFFMAN_ONLY
Z_RLE
Z_FIXED
Z_DEFAULT_STRATEGY
The default is Z_DEFAULT_STRATEGY.
๐ซง Bzip2 Compression Options ๐ซง
BlockSize100K => numberโ specify the number of 100K blocks bzip2 uses during compression. ๐ง
Valid values are from 1 to 9, where 9 is best compression.
This option is only valid if the Method is ZIP_CM_BZIP2. It's ignored otherwise.
The default is 1.
WorkFactor => numberโ specifies how much effort bzip2 should put in before resorting to a slower fallback compression algorithm. ๐ฎโ๐จ
Valid values range from 0 to 250, where 0 means use the default value 30.
This option is only valid if the Method is ZIP_CM_BZIP2. It's ignored otherwise.
The default is 0.
๐ช๏ธ Lzma and Xz Compression Options ๐ช๏ธ
Preset => numberโ used to choose the LZMA compression preset.
Valid values are 0-9 and LZMA_PRESET_DEFAULT.
0 is the fastest compression with the lowest memory usage and the lowest compression.
9 is the slowest compression with the highest memory usage but with the best compression.
This option is only valid if the Method is ZIP_CM_LZMA. It's ignored otherwise.
Defaults to LZMA_PRESET_DEFAULT (6).
Extreme => 0|1โ makes LZMA compression a whole lot slower, but gives you a small compression gain. ๐ฅ
This option is only valid if the Method is ZIP_CM_LZMA. It's ignored otherwise.
Defaults to 0.
๐ Other Options ๐
Time => $numberโ sets the last modified time field in the zip header to$number. โฐ
This field defaults to the time the IO::Compress::Zip object was created if this option isn't specified and the $input parameter is not a filename.
ExtAttr => $attrโ this option controls the "external file attributes" field in the central header of the zip file. This is a 4 byte field.
okay so if you're on a Unix-y system, this value lowkey defaults to
0100644 << 16
which is literally the vibe that says "yeah bestie, anyone extracting this zip can read AND write these files" ๐
. And for every other system? It just defaults to 0. mid, but okay.
"exTime => [$atime, $mtime, $ctime]"โ okay so this one wants an array ref with exactly three things in it:$atime,"mtime", and$ctimeโ aka last access time, last modification time, and creation time, in that order ๐. It uses these to set the extended timestamp field (ID is"UT") in the local zip header using all three values,$atime,$mtime,$ctime. And then it ALSO sets the extended timestamp field in the central zip header using$mtime. Two headers, one little timestamp glow-up โจ.
If any of the three values is "undef", that time value justโฆ doesn't get used. No stress. So say you only wanna set the $mtime:
exTime => [undef, $mtime, undef]
but wait โ if the "Minimal" option is true, this whole option gets ignored, no cap. And by default? No extended time field is created at all. periodt.
"exUnix2 => [$uid, $gid]"โ expects an array ref with exactly two elements:$uidand$gid, the numeric User ID (UID) and Group ID (GID) of whoever owns the files ๐.
When "exUnix2" shows up, it triggers creation of a Unix2 extra field (ID is "Ux") in the local zip header, populated with $uid and $gid. An empty Unix2 extra field also gets created in the central zip header. Matching set, iconic.
Heads up bestie โ the UID & GID are stored as 16-bit integers in the"Ux"field. If your UID or GID are 32-bit, use"exUnixN"instead. Don't get caught slippin' ๐.
If "Minimal" is true, this option is ignored. By default, no Unix2 extra field is created.
"exUnixN => [$uid, $gid]"โ same deal, wants an array ref with exactly two elements:$uidand$gid, the numeric User ID (UID) and Group ID (GID) of the file owners ๐.
When "exUnixN" is present it triggers a UnixN extra field (ID is "ux" โ lowercase, don't mix 'em up) in both the local and central zip headers. Populated with $uid and $gid. And here the UID & GID are stored as 32-bit integers โ the big girl version ๐
.
If "Minimal" is true, ignored. By default, no UnixN extra field is created.
"Comment => $comment"โ stores the contents of$commentin the Central File Header of the zip file ๐ฌ.
Wanna store a UTF8 comment? Set the "Efs" option to true. That's the move.
By default, no comment field is written to the zip file. it's giving silent treatment.
"ZipComment => $comment"โ stores the contents of$commentin the End of Central Directory record of the zip file ๐.
By default, no comment field is written to the zip file.
"Method => $method"โ controls which compression method gets used ๐ช. Right now the supported methods are: Store (aka no compression at all, why are you even here), Deflate, Bzip2, Zstd, Xz and Lzma.
The symbols ZIP_CM_STORE, ZIP_CM_DEFLATE, ZIP_CM_BZIP2, ZIP_CM_ZSTD, ZIP_CM_XZ and ZIP_CM_LZMA are how you select the method.
plot twist โ these constants are NOT imported by "IO::Compress::Zip" by default. So if you want 'em:
use IO::Compress::Zip qw(:zip_method);
use IO::Compress::Zip qw(:constants);
use IO::Compress::Zip qw(:all);
๐ Real talk: to make Bzip2 content, the module"IO::Compress::Bzip2"has to be installed. Try to create Bzip2 content without it and you get a fatal error, straight up. Same energy for Lzma: need"IO::Compress::Lzma"installed or it's a fatal error. Xz needs"IO::Compress::Xz". Zstd needs"IO::Compress::Zstd". No module, no content, fatal error, periodt.
The default method is ZIP_CM_DEFLATE. the standard, the classic, the moment โจ.
"TextFlag => 0|1"โ this parameter controls the setting of a bit in the zip central header. It's the little signal that says "hey, the data in this zip file/buffer is probably text" ๐.
In one-shot mode, this flag gets set to true if the Perl "-T" operator thinks the file contains text. She's self-aware like that.
The default is 0.
"ExtraFieldLocal => $data""ExtraFieldCentral => $data"โ"ExtraFieldLocal"stores extra metadata in the local header for the zip file/buffer;"ExtraFieldCentral"does the same thing for the matching central header. Two peas, one pod ๐ซถ.
An extra field = zero or more subfields. Each subfield = a two byte header followed by the subfield data.
You can hand over the list of subfields in any of these formats:
ExtraFieldLocal => [$id1, $data1,
$id2, $data2,
...
]
ExtraFieldLocal => [ [$id1 => $data1],
[$id2 => $data2],
...
]
ExtraFieldLocal => { $id1 => $data1,
$id2 => $data2,
...
}
Where $id1, $id2 are two byte subfield ID's.
If you go the hash syntax route, you've got no control over the order the ExtraSubFields get stored in, plus you cannot have SubFields with duplicate ID. pick your fighter ๐ฅ.
Alternatively, the list of subfields can be supplied as a scalar, like:
ExtraField => $rawdata
In that case "IO::Compress::Zip" will check that $rawdata consists of zero or more conformant sub-fields. she's checking your work, respectfully.
The Extended Time field (ID "UT"), set via the "exTime" option, and the Unix2 extra field (ID "Ux"), set via the "exUnix2" option, are both examples of extra fields. iconique examples, honestly.
If "Minimal" is true, this option is ignored.
The maximum size of an extra field is 65535 bytes. that's the limit, no exceptions ๐.
"Strict => 0|1"โ this is a placeholder option. that's it. that's the whole thing. a lil ghost ๐ป.
โจ Examples โจ
๐ Streaming
This very simple command line example shows off the streaming capabilities of the module. The code reads data from STDIN or all the files given on the commandline, compresses it, and writes the compressed data to STDOUT. chef's kiss ๐ฅ.
use strict ;
use warnings ;
use IO::Compress::Zip qw(zip $ZipError) ;
my $z = IO::Compress::Zip->new("-", Stream => 1)
or die "IO::Compress::Zip failed: $ZipError\n";
while (<>) {
$z->print("abcde");
}
$z->close();
Note the use of "-" to mean "STDOUT". Or you can use "\*STDOUT" if that's more your vibe.
So here's a little problem with creating a zip archive straight from STDIN โ peep the contents of the zip file, output.zip, that we just made (assuming you redirected it to a file called "output.zip"):
$ unzip -l output.zip
Archive: output.zip
Length Date Time Name
--------- ---------- ----- ----
12 2019-08-16 22:21
--------- -------
12 1 file
The archive member (filename) used is the empty string. it's giving mysterious ๐ซฅ.
If that doesn't suit your needs, you can explicitly set the filename used in the zip archive by specifying the Name option, like so:
my $z = IO::Compress::Zip->new("-", Name => "hello.txt", Stream => 1)
Now the contents of the zip file look like this:
$ unzip -l output.zip
Archive: output.zip
Length Date Time Name
--------- ---------- ----- ----
12 2019-08-16 22:22 hello.txt
--------- -------
12 1 file
glow up achieved โจ
๐ Compressing a file from the filesystem
To read the contents of the file "file1.txt" and write the compressed data to the file "file1.txt.zip", there are a few options.
Start by creating the compression object and opening the input file:
use strict ;
use warnings ;
use IO::Compress::Zip qw(zip $ZipError) ;
my $input = "file1.txt";
my $z = IO::Compress::Zip->new("file1.txt.zip")
or die "IO::Compress::Zip failed: $ZipError\n";
# open the input file
open my $fh, "<", "file1.txt"
or die "Cannot open file1.txt: $!\n";
# loop through the input file & write to the compressed file
while (<$fh>) {
$z->print($_);
}
# not forgetting to close the compressed file
$z->close();
and yes bestie, don't forget to close โ that's the golden rule ๐ซถ.
๐ Compressing multiple files
To create a zip file, "output.zip", that contains the compressed contents of the files "alpha.txt" and "beta.txt":
use strict ;
use warnings ;
use IO::Compress::Zip qw(zip $ZipError) ;
my $z = IO::Compress::Zip->new("output.zip", Name => "alpha.txt")
or die "IO::Compress::Zip failed: $ZipError\n";
# open the input file
open my $fh, "<", "file1.txt"
or die "Cannot open file1.txt: $!\n";
# loop through the input file & write to the compressed file
while (<$fh>) {
$z->print($_);
}
# move to next file
$z->newStream(Name => "beta.txt")
while (<$fh>) {
$z->print($_);
}
$z->close();
and that's the multi-file serve ๐
โ $z->newStream(Name => "beta.txt") is literally the plot twist that keeps the archive rolling.
๐ Methods ๐
okay bestie this is the part you came for โ all the methods you can call on your $z object. buckle up ๐ธ
๐ธ print
usage is literally this:
$z->print($data)
print $z $data
it compresses the contents of the $data parameter and outputs it. same behaviour as the print built-in, no cap. โจ
returns true if it succeeded. ๐
๐ธ printf
usage:
$z->printf($format, $data)
printf $z $format, $data
compresses and outputs the contents of $data. that's the whole vibe. ๐ฆ
returns true if successful.
๐ธ syswrite
usage, three flavours:
$z->syswrite $data
$z->syswrite $data, $length
$z->syswrite $data, $length, $offset
compresses and outputs the contents of $data.
returns the number of uncompressed bytes written, or undef if it flopped. ๐
๐ธ write
usage:
$z->write $data
$z->write $data, $length
$z->write $data, $length, $offset
compresses and outputs the contents of $data.
returns the number of uncompressed bytes written, or undef if unsuccessful. (yes it's basically the same energy as syswrite, they're twins ๐ซถ)
๐ธ flush
usage:
$z->flush;
$z->flush($flush_type);
flushes any pending compressed data out to the output file/buffer. bye pending data ๐
this method takes an optional param, $flush_type, that controls how the flushing happens. by default the $flush_type used is Z_FINISH. other valid values for $flush_type are Z_NO_FLUSH, Z_SYNC_FLUSH, Z_FULL_FLUSH and Z_BLOCK.
โ ๏ธ bestie, listen. it is strongly recommended that you only set theflush_typeparameter if you fully understand the implications of what it does โ overuse offlushcan seriously degrade the level of compression achieved. that's not a vibe, that's a warning. see thezlibdocumentation for the details.
returns true on success. ๐
๐ธ tell
usage:
$z->tell()
tell $z
returns the uncompressed file offset. that's it, that's the method ๐
๐ธ eof
usage:
$z->eof();
eof($z);
returns true if the close method has been called. iconic behaviour honestly.
๐ธ seek
usage:
$z->seek($position, $whence);
seek($z, $position, $whence);
gives you a sub-set of the seek functionality, with one big restriction: it's only legal to seek forward in the output file/buffer. attempting to seek backward is a fatal error. periodt. ๐ซ
empty parts of the file/buffer get NULL (0x00) bytes written into them.
the $whence parameter takes one of the usual values, namely SEEK_SET, SEEK_CUR or SEEK_END.
returns 1 on success, 0 on failure. โจ
๐ธ binmode
usage:
$z->binmode
binmode $z ;
this is a noop, provided just for completeness. it's giving "I'm here so the API looks whole" ๐
๐ธ opened
usage:
$z->opened()
returns true if the object currently refers to an opened file/buffer. vibe check passed โ
๐ธ autoflush
usage:
my $prev = $z->autoflush()
my $prev = $z->autoflush(EXPR)
if the $z object is associated with a file or a filehandle, this method returns the current autoflush setting for the underlying filehandle. if EXPR is present, and is non-zero, it will enable flushing after every write/print operation.
if $z is associated with a buffer, this method has no effect and always returns undef. ๐ญ
note that the special variable $| cannot be used to set or retrieve the autoflush setting. don't try it bestie, it won't work.
๐ธ input_line_number
usage:
$z->input_line_number()
$z->input_line_number(EXPR)
this method always returns undef when compressing. always. no matter what you pass it. ๐
๐ธ fileno
usage:
$z->fileno()
fileno($z)
if the $z object is associated with a file or a filehandle, fileno will return the underlying file descriptor. once the close method is called, fileno will return undef.
if the $z object is associated with a buffer, this method will return undef. buffer girlies stay losing on this one ๐
๐ธ close
usage:
$z->close() ;
close $z ;
flushes any pending compressed data and then closes the output file/buffer. the full send-off ๐
for most versions of Perl this method will be automatically invoked if the IO::Compress::Zip object is destroyed (either explicitly or by the variable with the reference to the object going out of scope). the exceptions are Perl versions 5.005 through 5.00504 and 5.8.0. in these cases, the close method will be called automatically, but not until global destruction of all live objects when the program is terminating. ๐ฌ
so, if you want your scripts to be able to run on all versions of Perl, you should call close explicitly and not rely on automatic closing. do it yourself, bestie, it's the safe route.
returns true on success, otherwise 0.
if the AutoClose option has been enabled when the IO::Compress::Zip object was created, and the object is associated with a file, the underlying file will also be closed. ๐
๐ธ newStream([OPTS])
usage:
$z->newStream( [OPTS] )
closes the current compressed data stream and starts a new one. fresh start energy โจ
OPTS consists of any of the options that are available when creating the $z object.
see the "Constructor Options" section for more details.
๐ธ deflateParams
usage:
$z->deflateParams
TODO ๐ that's genuinely all it says. we love an unfinished icon.
๐ Importing ๐
a number of symbolic constants are required by some methods in IO::Compress::Zip. none are imported by default. so if you want them, you gotta ask nicely.
:allโ importszip,$ZipErrorand all symbolic constants that can be used byIO::Compress::Zip. same as doing this:
use IO::Compress::Zip qw(zip $ZipError :constants) ;
:constantsโ import all symbolic constants. same as doing this:
use IO::Compress::Zip qw(:flush :level :strategy :zip_method) ;
:flushโ these symbolic constants are used by theflushmethod:
Z_NO_FLUSH
Z_PARTIAL_FLUSH
Z_SYNC_FLUSH
Z_FULL_FLUSH
Z_FINISH
Z_BLOCK
:levelโ these symbolic constants are used by theLeveloption in the constructor:
Z_NO_COMPRESSION
Z_BEST_SPEED
Z_BEST_COMPRESSION
Z_DEFAULT_COMPRESSION
:strategyโ these symbolic constants are used by theStrategyoption in the constructor:
Z_FILTERED
Z_HUFFMAN_ONLY
Z_RLE
Z_FIXED
Z_DEFAULT_STRATEGY
:zip_methodโ these symbolic constants are used by theMethodoption in the constructor:
ZIP_CM_STORE
ZIP_CM_DEFLATE
ZIP_CM_BZIP2
๐ EXAMPLES ๐
๐ธ Apache::GZip Revisited
see IO::Compress::FAQ ๐
๐ธ Working with Net::FTP
see IO::Compress::FAQ ๐ฆ
๐ SUPPORT ๐
general feedback/questions/bug reports should be sent to <https://github.com/pmqs/IO-Compress/issues> (preferred) or <https://rt.cpan.org/Public/Dist/Display.html?Name=IO-Compress>. they want to hear from you, fr fr ๐ซถ
โญ SEE ALSO โญ
the whole squad, alphabetically-ish:
- Compress::Zlib, IO::Compress::Gzip, IO::Uncompress::Gunzip, IO::Compress::Deflate, IO::Uncompress::Inflate, IO::Compress::RawDeflate, IO::Uncompress::RawInflate, IO::Compress::Bzip2, IO::Uncompress::Bunzip2, IO::Compress::Lzma, IO::Uncompress::UnLzma, IO::Compress::Xz, IO::Uncompress::UnXz, IO::Compress::Lzip, IO::Uncompress::UnLzip, IO::Compress::Lzop, IO::Uncompress::UnLzop, IO::Compress::Lzf, IO::Uncompress::UnLzf, IO::Compress::Zstd, IO::Uncompress::UnZstd, IO::Uncompress::AnyInflate, IO::Uncompress::AnyUncompress
- IO::Compress::FAQ
- File::GlobMapper, Archive::Zip, Archive::Tar, IO::Zlib
for RFC 1950, 1951 and 1952 see <https://datatracker.ietf.org/doc/html/rfc1950>, <https://datatracker.ietf.org/doc/html/rfc1951> and <https://datatracker.ietf.org/doc/html/rfc1952>
the zlib compression library was written by Jean-loup Gailly gzip@prep.ai.mit.edu and Mark Adler madler@alumni.caltech.edu. legends, honestly ๐
the primary site for the zlib compression library is <http://www.zlib.org>.
the primary site for the zlib-ng compression library is <https://github.com/zlib-ng/zlib-ng>.
the primary site for gzip is <http://www.gzip.org>.
๐ธ AUTHOR ๐ธ
this module was written by Paul Marquess, pmqs@cpan.org. king behaviour ๐
๐ MODIFICATION HISTORY ๐
see the Changes file. iykyk ๐
๐ COPYRIGHT AND LICENSE ๐
Copyright (c) 2005-2026 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.
okay bestie that's the whole entire page, we made it to the end and it was long but we ate ๐ that's the IO::Compress::Zip manpage from perl v5.44.0, dated 2026-10-17 โ go forth and zip your little heart out, slay โจ๐๐ฆ
๐ฆ where this page comes from
- arch rolling: perl 5.44.0-1 ยท Artistic-1.0-Perl AND GPL-1.0-or-later
- ๐ girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms