我写了一些做同样事情的代码。为了更好地理解,这里有一些额外的片段:
$this->fh = $fileHandle;
$this->startOffset = ftell($fileHandle); // current location in the file
// reading basic 7 byte header block
$array = unpack('vheaderCrc/CblockType/vflags/vheaderSize', fread($this->fh, 7));
$this->headerCrc = $array['headerCrc'];
$this->blockType = $array['blockType'];
$this->flags = $array['flags'];
$this->hsize = $array['headerSize'];
$this->addSize = 0; // size of data after the header
// -- check CRC of block header --
$offset = ftell($this->fh);
fseek($this->fh, $this->startOffset + 2, SEEK_SET);
$crcData = fread($this->fh, $this->hsize - 2);
// only the 4 lower order bytes are used
$crc = crc32($crcData) & 0xffff;
// igonore blocks with no CRC set (same as twice the blockType)
if ($crc !== $this->headerCrc && $this->headerCrc !== 0x6969 // SRR Header
&& $this->headerCrc !== 0x6a6a // SRR Stored File
&& $this->headerCrc !== 0x7171 // SRR RAR block
&& $this->blockType !== 0x72 // RAR marker block (fixed: magic number)
) {
array_push($warnings, 'Invalid block header CRC found: header is corrupt.');
}
// set offset back to where we started from
fseek($this->fh, $offset, SEEK_SET);
我在几个SRR文件上对其进行了测试,它按预期工作。我从阅读基本的 7 字节标头开始。标题的大小可以在那里找到。我用它来获取 crc32 函数的正确数据量。我注意到,当您将其转换为十六进制时,比较时会出现误报:'0f00'!='f00'。您需要用零填充它。这就是为什么我保留 crc32() 和unpack () 的十进制表示进行比较的原因。此外,如果设置了某些标头标志,文件块的字段数可能会有所不同:您可能选择了错误的大小。