我希望我的 Perl 脚本从文件加载二进制数据。但是,如果文件开头出现 _ISCOMPRESSED_
header ,则该文件可以直接加载,也可以需要解压缩 (zlib)。
我已经能够成功加载未压缩的文件并识别标题:
(open my ($fh), "<", $fileName) or (return 0);
binmode $fh;
my $fileHeader;
sysread $fh, $fileHeader, 14;
if( $fileHeader eq "_ISCOMPRESSED_" ){
# Here, need to decompress the filestream and update the $fh to point toward uncompressed data
}
else{
# Read it from the begining
sysseek $fh,0,0;
}
# Read the data using the file handle
sysread $fh,$self->{'sig'},4;
sysread $fh,$self->{'version'},4;
我现在想使用 Zlib 解压缩数据 block 并更新文件句柄 $fh
以分配未压缩的数据。
我应该怎么做?是否可以在不将未压缩数据写入磁盘的情况下完成此操作?
最佳答案
perl 附带的解压模块可以从现有的打开文件句柄中读取。读取将从当前偏移量开始,从而可以轻松跳过标题。 IO::Uncompress::*
模块特别创建可与普通 I/O 函数一起使用的文件句柄对象,以允许透明使用;创建后,您的代码并不关心它是压缩的还是纯源文件。像这样的东西:
#!/usr/bin/env perl
use warnings;
use strict;
# I don't have a zlib-flate to test for sure; I think this is the right module
use IO::Uncompress::Inflate;
my $fileName = "data.compressed";
my $fh;
open my $realfh, "<:raw", $fileName
or die "Unable to open $fileName: $!\n";
read $realfh, my $header, 14;
if ($header eq "_ISCOMPRESSED_") {
$fh = IO::Uncompress::Inflate->new($realfh, AutoClose => 1)
or die "Unable to open decompression stream!\n";
} else {
seek $realfh, 0, 0;
$fh = $realfh;
}
read $fh, $self->{'sig'}, 4;
read $fh, $self->{'version'}, 4;
# etc.
close $fh;
如果您像您看起来那样进行大量小型输入操作,我会使用 read
而不是 sysread
来利用内部缓冲。但重要的是要保持一致;在同一个文件句柄上混合两种形式将导致看似丢失数据的问题。
关于perl - 从 Perl 中具有数据偏移量的文件加载 zlib 压缩数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/73519099/