在 zlib_decode() 之后获取压缩字节大小?

Get compressed byte size after zlib_decode()?

我正在尝试使用 PHP 来解析在 Delphi 中创建的自定义 gzip 存档文件格式(不是我的代码!)。格式基本上是:

4-byte integer: count of files in archive

for each compressed file: 
  4-byte integer: filename length [n]
  [n] bytes: filename
  4-byte integer: uncompressed file length [m]
  [????] bytes: gzipped content

我可以读取文件并使用 zlib_decode() with a max uncompressed length of [m] bytes on the remainder of the file after I know the length ([m]), but then I'm stuck because I don't know how far into the substring I should go to find the next filename -- zlib_decode() doesn't return the number of compressed bytes that it processed before stopping. Since this is a custom format, it doesn't seem like I can use the normal gzopen()/gzread() 函数正确解码第一个压缩文件,因为整个文件没有被压缩(我试过,它不起作用)。

此代码在 Delphi 中有效,因为显然您可以在普通文件读取函数和 System.ZLib 解码函数之间来回传递文件​​句柄——您可以读取 [m] 个未压缩的字节和指针将保留在最后一个压缩字节处——但 PHP 似乎不支持以这种方式在正常读取和 gzip 读取之间动态切换。

我是否在 PHP 中遗漏了一个明显的方法来处理像这样的混合内容文件格式,其中元数据和压缩数据以这种方式堆叠在一起?还是我运气不好不知道压缩后的数据长度?

一个肮脏的解决方法是重新压缩每个文件的内容,因为我能够解析它,用它来计算压缩长度,并手动调整原始文件中的文件指针,如下所示:

$current_pos = ftell($handle);
$skip_length = strlen(gzencode($uncompressed_text,9,FORCE_DEFLATE));
fseek($handle, $skip_length+$current_pos);

这行得通,但感觉很老套。我仍然愿意接受任何更好的方法。

编辑:

请注意,这最终失败了。但是,我很幸运能够提前知道预期的文件名列表,并且我能够执行以下操作(更可靠,因为 zlib_decode() 将尽可能多地解码并丢弃其余部分):

foreach ($filenames as $thisFilename) {
    $thisPos = strpos($rawData, $thisFilename);
    $gzresult = zlib_decode(substr($rawData, $thisPos + strlen($table) + 8)); // skip 8 bytes for filename size and uncompressed data size, which are useless info.
}