内容

名称

IO::Uncompress::Unzip - 读取 zip 文件/缓冲区

概要

use IO::Uncompress::Unzip qw(unzip $UnzipError) ;

my $status = unzip $input => $output [,OPTS]
    or die "unzip failed: $UnzipError\n";

my $z = IO::Uncompress::Unzip->new( $input [OPTS] )
    or die "unzip failed: $UnzipError\n";

$status = $z->read($buffer)
$status = $z->read($buffer, $length)
$status = $z->read($buffer, $length, $offset)
$line = $z->getline()
$char = $z->getc()
$char = $z->ungetc()
$char = $z->opened()

$status = $z->inflateSync()

$data = $z->trailingData()
$status = $z->nextStream()
$data = $z->getHeaderInfo()
$z->tell()
$z->seek($position, $whence)
$z->binmode()
$z->fileno()
$z->eof()
$z->close()

$UnzipError ;

# IO::File mode

<$z>
read($z, $buffer);
read($z, $buffer, $length);
read($z, $buffer, $length, $offset);
tell($z)
seek($z, $position, $whence)
binmode($z)
fileno($z)
eof($z)
close($z)

描述

此模块提供一个 Perl 接口,允许读取 zlib 文件/缓冲区。

有关写入 zip 文件/缓冲区的信息,请参见配套模块 IO::Compress::Zip。

该模块的主要目的是提供对 zip 文件和缓冲区的流式读取访问。

目前,IO::Uncompress::Unzip 支持以下压缩方法

存储 (0)
压缩 (8)
Bzip2 (12)

要读取 Bzip2 内容,必须安装模块 IO::Uncompress::Bunzip2

Lzma (14)

要读取 LZMA 内容,必须安装模块 IO::Uncompress::UnLzma

Xz (95)

要读取 Xz 内容,必须安装模块 IO::Uncompress::UnXz

Zstandard (93)

要读取 Zstandard 内容,必须安装模块 IO::Uncompress::UnZstd

函数式接口

提供了一个顶级函数 unzip,用于在缓冲区和/或文件之间执行“一次性”解压缩。有关解压缩过程的更精细控制,请参阅"OO 接口"部分。

use IO::Uncompress::Unzip qw(unzip $UnzipError) ;

unzip $input_filename_or_reference => $output_filename_or_reference [,OPTS]
    or die "unzip failed: $UnzipError\n";

函数式接口需要 Perl5.005 或更高版本。

unzip $input_filename_or_reference => $output_filename_or_reference [, OPTS]

unzip 至少需要两个参数,$input_filename_or_reference$output_filename_or_reference,以及零个或多个可选参数(请参阅"可选参数")。

$input_filename_or_reference 参数

参数 $input_filename_or_reference 用于定义压缩数据的来源。

它可以采用以下形式之一

文件名

如果 $input_filename_or_reference 参数是一个简单的标量,则假定它是一个文件名。此文件将被打开以供读取,并且输入数据将从该文件读取。

文件句柄

如果 $input_filename_or_reference 参数是一个文件句柄,则输入数据将从该文件句柄读取。字符串 '-' 可以用作标准输入的别名。

标量引用

如果 $input_filename_or_reference 是一个标量引用,输入数据将从 $$input_filename_or_reference 读取。

数组引用

如果 $input_filename_or_reference 是一个数组引用,数组中的每个元素都必须是一个文件名。

输入数据将依次从每个文件读取。

在解压缩任何数据之前,将遍历整个数组以确保它只包含有效的文件名。

输入文件通配符字符串

如果 $input_filename_or_reference 是一个由字符 "<" 和 ">" 分隔的字符串,unzip 将假定它是一个输入文件通配符字符串。输入是与文件通配符匹配的文件列表。

有关更多详细信息,请参见 File::GlobMapper

如果 $input_filename_or_reference 参数是任何其他类型,将返回 undef

$output_filename_or_reference 参数

$output_filename_or_reference 参数用于控制解压缩数据的目标。此参数可以采用以下形式之一。

文件名

如果 $output_filename_or_reference 参数是一个简单的标量,则假定它是一个文件名。将打开此文件以供写入,并将解压缩的数据写入其中。

文件句柄

如果 $output_filename_or_reference 参数是一个文件句柄,则解压缩的数据将写入其中。字符串 '-' 可用作标准输出的别名。

标量引用

如果 $output_filename_or_reference 是一个标量引用,则解压缩的数据将存储在 $$output_filename_or_reference 中。

数组引用

如果 $output_filename_or_reference 是一个数组引用,则解压缩的数据将被推送到数组中。

输出文件通配符

如果 $output_filename_or_reference 是一个由字符 "<" 和 ">" 分隔的字符串,unzip 将假定它是一个输出文件通配符字符串。输出是与文件通配符匹配的文件列表。

$output_filename_or_reference 是一个文件通配符字符串时,$input_filename_or_reference 也必须是一个文件通配符字符串。任何其他情况都是错误。

有关更多详细信息,请参见 File::GlobMapper

如果 $output_filename_or_reference 参数是任何其他类型,将返回 undef

Notes

$input_filename_or_reference 映射到多个压缩文件/缓冲区,而 $output_filename_or_reference 是单个文件/缓冲区时,解压缩后 $output_filename_or_reference 将包含来自每个输入文件/缓冲区的全部解压缩数据的串联。

Optional Parameters

单次函数 unzip 的可选参数(在很大程度上)与在 "Constructor Options" 部分中定义的 OO 接口中使用的参数相同。例外情况如下所示

AutoClose => 0|1

此选项适用于任何作为文件句柄的 unzip 输入或输出数据流。

如果指定了 AutoClose,并且其值为 true,则 unzip 完成后将导致所有输入和/或输出文件句柄关闭。

此参数默认为 0。

BinModeOut => 0|1

此选项现在是一个无操作选项。所有文件都将以二进制模式写入。

Append => 0|1

此选项的行为取决于输出数据流的类型。

  • 缓冲区

    如果启用了 Append,所有解压缩数据都将追加到输出缓冲区的末尾。否则,在将任何解压缩数据写入输出缓冲区之前,将清除输出缓冲区。

  • 文件名

    如果启用了 Append,则该文件将以追加模式打开。否则,在将任何解压缩数据写入该文件之前,将截断该文件的内容(如果有)。

  • 文件句柄

    如果启用了 Append,则在将任何解压缩数据写入文件句柄之前,将通过调用 seek 将文件句柄定位到文件末尾。否则,文件指针将不会移动。

当指定 Append 并将其设置为 true 时,它将追加所有解压缩数据到输出数据流。

因此,当输出是文件句柄时,它将在写入任何解压缩数据之前执行 seek 到文件末尾的操作。如果输出是文件名,它将被打开以进行追加。如果输出是缓冲区,所有解压缩数据都将追加到现有缓冲区。

相反,当未指定 Append 或它存在且设置为 false 时,它将按如下方式操作。

当输出是文件名时,它将在写入任何解压缩数据之前截断文件的内容。如果输出是文件句柄,它的位置将不会改变。如果输出是缓冲区,它将在输出任何解压缩数据之前被清除。

默认值为 0。

MultiStream => 0|1

如果输入文件/缓冲区包含多个压缩数据流,此选项将把所有数据流解压缩为单个数据流。

默认值为 0。

TrailingData => $scalar

返回解压缩完成后,压缩数据流之后立即出现的数据(如果有)。

当压缩数据流之后紧跟着有用的信息,并且您不知道压缩数据流的长度时,可以使用此选项。

如果输入是缓冲区,trailingData 将返回从压缩数据流末尾到缓冲区末尾的所有内容。

如果输入是文件句柄,trailingData 将返回压缩数据流末尾到达后,文件句柄输入缓冲区中剩余的数据。然后,您可以使用文件句柄读取输入文件的其余部分。

如果输入是文件名,则不要使用 trailingData

如果您在开始解压缩之前知道压缩数据流的长度,可以通过设置 InputLength 选项来避免使用 trailingData

示例

假设您有一个 zip 文件 file1.zip,它只包含一个成员,您可以读取它并将解压缩后的数据写入文件 file1.txt,如下所示。

use strict ;
use warnings ;
use IO::Uncompress::Unzip qw(unzip $UnzipError) ;

my $input = "file1.zip";
my $output = "file1.txt";
unzip $input => $output
    or die "unzip failed: $UnzipError\n";

如果您有一个包含多个成员的 zip 文件,并且想要从文件中读取特定成员,例如 "data1",请使用 Name 选项

use strict ;
use warnings ;
use IO::Uncompress::Unzip qw(unzip $UnzipError) ;

my $input = "file1.zip";
my $output = "file1.txt";
unzip $input => $output, Name => "data1"
    or die "unzip failed: $UnzipError\n";

或者,如果您想将 "data1" 成员读入内存,请对 output 参数使用标量引用。

use strict ;
use warnings ;
use IO::Uncompress::Unzip qw(unzip $UnzipError) ;

my $input = "file1.zip";
my $output ;
unzip $input => \$output, Name => "data1"
    or die "unzip failed: $UnzipError\n";
# $output now contains the uncompressed data

要从现有的 Perl 文件句柄 $input 读取,并将解压缩后的数据写入缓冲区 $buffer

use strict ;
use warnings ;
use IO::Uncompress::Unzip qw(unzip $UnzipError) ;
use IO::File ;

my $input = IO::File->new( "<file1.zip" )
    or die "Cannot open 'file1.zip': $!\n" ;
my $buffer ;
unzip $input => \$buffer
    or die "unzip failed: $UnzipError\n";

面向对象接口

构造函数

IO::Uncompress::Unzip 的构造函数格式如下所示

my $z = IO::Uncompress::Unzip->new( $input [OPTS] )
    or die "IO::Uncompress::Unzip failed: $UnzipError\n";

成功时返回一个 IO::Uncompress::Unzip 对象,失败时返回 undef。变量 $UnzipError 将在失败时包含错误消息。

如果您运行的是 Perl 5.005 或更高版本,则从 IO::Uncompress::Unzip 返回的对象 $z 可以像 IO::File 文件句柄一样使用。这意味着所有正常的输入文件操作都可以使用 $z 执行。例如,要从压缩文件/缓冲区读取一行,可以使用以下两种形式之一

$line = $z->getline();
$line = <$z>;

强制参数$input用于确定压缩数据的来源。此参数可以采用三种形式之一。

文件名

如果$input参数是标量,则假定它是一个文件名。此文件将被打开以供读取,压缩数据将从其中读取。

文件句柄

如果$input参数是文件句柄,则压缩数据将从其中读取。字符串 '-' 可以用作标准输入的别名。

标量引用

如果$input是标量引用,则压缩数据将从$$input中读取。

构造函数选项

下面定义的选项名称不区分大小写,并且可以可选地以 '-' 为前缀。因此以下所有内容都是有效的

-AutoClose
-autoclose
AUTOCLOSE
autoclose

OPTS 是以下选项的组合

Name => "membername"

从 zip 文件中打开 "membername" 以供读取。

Efs => 0| 1

当此选项设置为 true 并且正在读取的 zip 档案具有 "语言编码标志" (EFS) 设置时,成员名称将被假定为以 UTF-8 编码。

如果 zip 档案中的成员名称在启用此选项时不是有效的 UTF-8,则脚本将以错误消息终止。

请注意,此选项仅适用于 Perl 5.8.4 或更高版本。

此选项默认为 **false**。

AutoClose => 0|1

此选项仅在$input参数是文件句柄时有效。如果指定,并且值为 true,则它将导致文件在调用close方法或销毁 IO::Uncompress::Unzip 对象后关闭。

此参数默认为 0。

MultiStream => 0|1

将整个 zip 文件/缓冲区视为单个压缩数据流。在多流模式下读取时,zip 文件/缓冲区中的每个成员将依次解压缩,直到遇到文件/缓冲区的末尾。

此参数默认为 0。

Prime => $string

此选项将在处理输入文件/缓冲区之前解压缩$string的内容。

当压缩数据嵌入到另一个文件/数据结构中,并且无法在不读取前几个字节的情况下确定压缩数据开始的位置时,此选项很有用。如果是这种情况,可以使用此选项使用这些字节对解压缩进行预先处理

Transparent => 0|1

如果设置了此选项,并且输入文件/缓冲区不是压缩数据,模块将允许读取它。

此外,如果输入文件/缓冲区确实包含压缩数据,并且其后紧跟着非压缩数据,则设置此选项将使此模块将整个文件/缓冲区视为单个数据流。

此选项默认为 1。

BlockSize => $num

读取压缩输入数据时,IO::Uncompress::Unzip 将以 $num 字节的块大小读取数据。

此选项默认为 4096。

InputLength => $size

如果存在此选项,它将限制从输入文件/缓冲区读取的压缩字节数为 $size。此选项可用于压缩数据流之后存在有用数据的情况,并且您事先知道压缩数据流的确切长度。

此选项主要用于从文件句柄读取时,在这种情况下,文件指针将指向压缩数据流之后的第一个字节。

此选项默认为关闭。

Append => 0|1

此选项控制 read 方法对解压缩数据的处理方式。

如果设置为 1,所有解压缩数据将附加到 read 方法的输出参数。

如果设置为 0,read 方法的输出参数的内容将被解压缩数据覆盖。

默认值为 0。

Strict => 0|1

此选项控制在执行解压缩时是否使用下面定义的额外检查。当 Strict 打开时,将执行额外的测试,当 Strict 关闭时,将不执行它们。

此选项的默认值为关闭。

示例

待办事项

方法

read

用法是

$status = $z->read($buffer)

读取一段压缩数据(压缩块的大小由构造函数中的 Buffer 选项决定),解压缩它并将任何解压缩的数据写入 $buffer。如果在构造函数中设置了 Append 参数,则解压缩的数据将被追加到 $buffer 参数。否则 $buffer 将被覆盖。

返回写入 $buffer 的解压缩字节数,如果遇到文件结尾则返回零,如果发生错误则返回负数。

read

用法是

$status = $z->read($buffer, $length)
$status = $z->read($buffer, $length, $offset)

$status = read($z, $buffer, $length)
$status = read($z, $buffer, $length, $offset)

尝试将 $length 字节的解压缩数据读入 $buffer

这种形式的 read 方法与前一种方法的主要区别在于,这种方法将尝试返回正好 $length 字节。只有在遇到文件结尾或 IO 错误时,此函数才会不返回 $length 字节。

返回写入 $buffer 的解压缩字节数,如果遇到文件结尾则返回零,如果发生错误则返回负数。

getline

用法是

$line = $z->getline()
$line = <$z>

读取一行。

此方法完全支持使用变量 $/(或当 English 处于使用状态时使用 $INPUT_RECORD_SEPARATOR$RS)来确定什么构成行尾。段落模式、记录模式和文件全部读取模式都受支持。

getc

用法是

$char = $z->getc()

读取一个字符。

ungetc

用法是

$char = $z->ungetc($string)

inflateSync

用法是

$status = $z->inflateSync()

待办事项

getHeaderInfo

用法是

$hdr  = $z->getHeaderInfo();
@hdrs = $z->getHeaderInfo();

此方法返回一个哈希引用(在标量上下文中)或一个列表或哈希引用(在数组上下文中),其中包含有关压缩数据流中每个头字段的信息。

tell

用法是

$z->tell()
tell $z

返回解压缩的文件偏移量。

eof

用法是

$z->eof();
eof($z);

如果已到达压缩输入流的末尾,则返回 true。

seek

$z->seek($position, $whence);
seek($z, $position, $whence);

提供 seek 功能的子集,限制是只能在输入文件/缓冲区中向前移动。尝试向后移动将导致致命错误。

请注意,此模块中 seek 的实现不提供对压缩文件/缓冲区的真正随机访问。它的工作原理是从文件/缓冲区中的当前偏移量解压缩数据,直到它到达 seek 参数中指定的解压缩偏移量。对于非常小的文件,这可能是可以接受的行为。对于大型文件,这可能会导致不可接受的延迟。

$whence 参数采用一个常用的值,即 SEEK_SET、SEEK_CUR 或 SEEK_END。

成功返回 1,失败返回 0。

binmode

用法是

$z->binmode
binmode $z ;

这是一个为了完整性而提供的空操作。

opened

$z->opened()

如果对象当前引用的是已打开的文件/缓冲区,则返回 true。

autoflush

my $prev = $z->autoflush()
my $prev = $z->autoflush(EXPR)

如果 $z 对象与文件或文件句柄相关联,则此方法将返回底层文件句柄的当前自动刷新设置。如果存在 EXPR 且不为零,则它将在每次写入/打印操作后启用刷新。

如果 $z 与缓冲区相关联,则此方法无效,始终返回 undef

注意 特殊变量 $| 不能 用于设置或检索自动刷新设置。

input_line_number

$z->input_line_number()
$z->input_line_number(EXPR)

返回当前未压缩的行号。如果存在 EXPR,则它将设置行号。请注意,设置行号不会更改正在读取的文件/缓冲区中的当前位置。

$/ 的内容用于确定什么构成行终止符。

fileno

$z->fileno()
fileno($z)

如果 $z 对象与文件或文件句柄相关联,则 fileno 将返回底层文件描述符。一旦调用 close 方法,fileno 将返回 undef

如果 $z 对象与缓冲区相关联,则此方法将返回 undef

close

$z->close() ;
close $z ;

关闭输出文件/缓冲区。

对于大多数版本的 Perl,如果 IO::Uncompress::Unzip 对象被销毁(无论是显式销毁还是通过对对象的引用的变量超出范围),则此方法将自动调用。例外情况是 Perl 版本 5.005 到 5.00504 和 5.8.0。在这些情况下,close 方法将自动调用,但直到程序终止时所有活动对象的全局销毁才会调用。

因此,如果您希望您的脚本能够在所有版本的 Perl 上运行,您应该显式调用 close,而不是依赖于自动关闭。

成功返回 true,否则返回 0。

如果在创建 IO::Uncompress::Unzip 对象时启用了 AutoClose 选项,并且对象与文件相关联,则底层文件也将被关闭。

nextStream

用法是

my $status = $z->nextStream();

跳到输入文件/缓冲区中的下一个压缩数据流。如果找到新的压缩数据流,则 eof 标记将被清除,并且 $. 将重置为 0。

如果在 zip 存档之后立即存在尾部数据,并且启用了 Transparent 选项,则此方法将认为该尾部数据是 zip 存档的另一个成员。

如果找到新的流,则返回 1;如果未找到,则返回 0;如果遇到错误,则返回 -1。

trailingData

用法是

my $data = $z->trailingData();

返回数据(如果有),该数据在解压缩完成后立即出现在压缩数据流之后。只有在遇到压缩数据流的末尾后,才调用此方法才有意义。

当压缩数据流之后紧跟着有用的信息,并且您不知道压缩数据流的长度时,可以使用此选项。

如果输入是缓冲区,trailingData 将返回从压缩数据流末尾到缓冲区末尾的所有内容。

如果输入是文件句柄,trailingData 将返回压缩数据流末尾到达后,文件句柄输入缓冲区中剩余的数据。然后,您可以使用文件句柄读取输入文件的其余部分。

如果输入是文件名,则不要使用 trailingData

如果您在开始解压缩之前知道压缩数据流的长度,则可以通过在构造函数中设置 InputLength 选项来避免使用 trailingData

导入

目前 IO::Uncompress::Unzip 不需要任何符号常量。

:all

导入 unzip$UnzipError。与执行以下操作相同

use IO::Uncompress::Unzip qw(unzip $UnzipError) ;

示例

使用 Net::FTP

参见 IO::Compress::FAQ

遍历 zip 文件

以下代码可用于遍历 zip 文件,一次处理一个压缩数据流。

use IO::Uncompress::Unzip qw($UnzipError);

my $zipfile = "somefile.zip";
my $u = IO::Uncompress::Unzip->new( $zipfile )
    or die "Cannot open $zipfile: $UnzipError";

my $status;
for ($status = 1; $status > 0; $status = $u->nextStream())
{

    my $name = $u->getHeaderInfo()->{Name};
    warn "Processing member $name\n" ;

    my $buff;
    while (($status = $u->read($buff)) > 0) {
        # Do something here
    }

    last if $status < 0;
}

die "Error processing $zipfile: $!\n"
    if $status < 0 ;

读取每个单独的压缩数据流,直到到达逻辑文件末尾。然后调用 nextStream。这将跳到下一个压缩数据流的开头,并清除文件末尾标志。

还值得注意的是,nextStream 可以随时调用 - 您不必等到用完压缩数据流才能跳到下一个流。

将完整的 zip 文件解压缩到磁盘

Daniel S. Sterling 编写了一个脚本,该脚本使用 IO::Uncompress::UnZip 读取 zip 文件并将内容解压缩到磁盘。

脚本可从 https://gist.github.com/eqhmcow/5389877 获取。

支持

一般反馈/问题/错误报告应发送至 https://github.com/pmqs/IO-Compress/issues(首选)或 https://rt.cpan.org/Public/Dist/Display.html?Name=IO-Compress

另请参阅

Compress::ZlibIO::Compress::GzipIO::Uncompress::GunzipIO::Compress::DeflateIO::Uncompress::InflateIO::Compress::RawDeflateIO::Uncompress::RawInflateIO::Compress::Bzip2IO::Uncompress::Bunzip2IO::Compress::LzmaIO::Uncompress::UnLzmaIO::Compress::XzIO::Uncompress::UnXzIO::Compress::LzipIO::Uncompress::UnLzipIO::Compress::LzopIO::Uncompress::UnLzopIO::Compress::LzfIO::Uncompress::UnLzfIO::Compress::ZstdIO::Uncompress::UnZstdIO::Uncompress::AnyInflateIO::Uncompress::AnyUncompress

IO::Compress::常见问题解答

File::GlobMapperArchive::ZipArchive::TarIO::Zlib

有关 RFC 1950、1951 和 1952,请参阅 https://datatracker.ietf.org/doc/html/rfc1950https://datatracker.ietf.org/doc/html/rfc1951https://datatracker.ietf.org/doc/html/rfc1952

zlib 压缩库由 Jean-loup Gailly [email protected] 和 Mark Adler [email protected] 编写。

zlib 压缩库的主要网站是 http://www.zlib.org

zlib-ng 压缩库的主要网站是 https://github.com/zlib-ng/zlib-ng

gzip 的主要网站是 http://www.gzip.org

作者

此模块由 Paul Marquess 编写,[email protected]

修改历史

请参阅 Changes 文件。

版权和许可

版权所有 (c) 2005-2023 Paul Marquess。保留所有权利。

本程序是自由软件;您可以根据与 Perl 本身相同的条款重新发布和/或修改它。