Perl - 如何使用 Digest::CRC 计算 M 维数组(N<M)中 N 个字节的 CRC16

Perl - How to calculate CRC16 of N bytes from array M-dimensional (with N<M) using Digest::CRC

我需要计算从大小为 M(一对 Kb,与我的范围不太相关)的二进制文件中提取的 N 字节的 CRC16(示例中为 5,为简单起见)。

printf "offset\tvalue\tcrc16\n";
#Read N bytes from file and copy in the container
for my $counter (0 .. 5- 1)
{
    my $oneByte;
    read(FH, $oneByte, 1) or die "Error reading $inFile!";
    my $ctx2 = Digest::CRC->new( type => 'crc16' );
    my $digest2 = ($ctx2->add($oneByte))->hexdigest;
    # PRINT for debugging
    printf "0x%04X\t0x%02X\t0x", $counter, ord $oneByte;
    print $digest2, "\n";
}

考虑这个二进制输入

我得到结果:

该脚本正在逐字节执行 CRC16(顺便说一句正确),但我需要 5 个字节的完整二进制流的 CRC16(预期值应为 0x6CD6)。 我的脚本哪里错了?

您可以使用 ->add。您可以一次传递整个字符串,逐块传递,或逐字符传递。

$ perl -M5.010 -MDigest::CRC -e'
   my $d = Digest::CRC->new( type => "crc16" );
   $d->add("\x49\x34\x49\x31\x31");
   say $d->hexdigest;
'
6cd6

$ perl -M5.010 -MDigest::CRC -e'
   my $d = Digest::CRC->new( type => "crc16" );
   $d->add($_) for "\x49", "\x34", "\x49", "\x31", "\x31";
   say $d->hexdigest;
'
6cd6

如图所示,使用单个对象,并在调用 ->digest(等)之前添加每个字节,因为这会重置进程。

调用 hexdigestdigestb64digest 会清除缓冲区并从头开始下一个摘要。 (如果您正在计算多个 files/streams 的摘要,您不希望来自一个流的数据影响另一个流的摘要)。

所以等到流被完全读取后再调用digest

... {
    ...
    $ctx2->add($oneByte);
}
print "digest = ", $ctx2->hexdigest, "\n";

或者为了帮助调试,保存流并在每个新字节后重新消化流

my $manyBytes = "";
... {
    ...
    $manyBytes .= $oneByte;
    $digest2 = $ctx2->add($manyBytes)->hexdigest;
    ...
}