使用Perl中的数据偏移量从文件加载zlib压缩数据

wljmcqd8  于 2022-11-15  发布在  Perl
关注(0)|答案(1)|浏览(140)

我想让我的Perl脚本从一个文件中加载二进制数据。然而,如果文件头_ISCOMPRESSED_出现在文件的开头,这个文件可以直接加载或者需要解压缩(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解压缩数据块,并更新文件句柄$fh以分配未压缩的数据。
我应该怎么做,是否有可能做到这一点,而不写未压缩的数据在磁盘上?

4smxwvx5

4smxwvx51#

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来利用内部缓冲。在同一个文件句柄上混合使用这两种形式将导致看似丢失数据的问题。

相关问题