在Perl + EOF处理中将位写入(和读取)二进制文件

Asc*_*ari 3 binary perl bit-manipulation

我有两个相关的问题(在Perl中):

  1. 将数据写入二进制文件,格式为:单位标志后跟8位
  2. 回读相同的格式

我试过这个(和其他变化,但对于我的生活,我无法弄清楚这一点):

binmode(OUT);
my $bit = pack("B1", '1');
my $byte = pack("H2", "02");
print OUT $bit . $byte;
Run Code Online (Sandbox Code Playgroud)

使用十六进制编辑器,我看到我得到16位:

1000000000000020
Run Code Online (Sandbox Code Playgroud)

我想要的是9位:

100000020
Run Code Online (Sandbox Code Playgroud)

另外:假设我写出了其中两种模式.这意味着我最终得到9 + 9 = 18位.我不知道如何处理最后一个字节(填充?)

这是压缩和解压缩文件,空间非常宝贵.我希望有一些简单的惯用方法可以做到这一点,我不知道.

ike*_*ami 5

文件是字节序列.如果要打印出位,则必须使用某种形式的缓冲.

my $bits = '';
$bits .= '1';                                        # Add 1 bit.
$bits .= unpack('B8', pack('C', 0x02));              # Add 8 bits.
$bits .= substr(unpack('B8', pack('C', 0x02)), -6);  # Add 6 bits.
Run Code Online (Sandbox Code Playgroud)

这打印尽可能多的缓冲区:

my $len = ( length($bits) >> 3 ) << 3;
print($fh, pack('B*', substr($bits, 0, $len, '')));
Run Code Online (Sandbox Code Playgroud)

你最终需要填充缓冲区,以便你有8位的倍数,以便清除其余的.你可以简单地用零填充.

$bits .= "0" x ( -length($bits) % 8 );
Run Code Online (Sandbox Code Playgroud)

但是,如果你很聪明,你可以提出一个填充方案,可以用来指示文件实际结束的位置.请记住,您不能再依赖文件长度了.如果您不使用智能填充方案,则必须使用其他方法.

智能填充方案的一个示例是:

$bits .= "0";
$bits .= "1" x ( -length($bits) % 8 );
Run Code Online (Sandbox Code Playgroud)

然后,对于unpad,删除所有尾随1位和0之前的位.