【问题标题】:Get compressed byte size after zlib_decode()?在 zlib_decode() 之后获取压缩字节大小?
【发布时间】:2015-09-03 23:33:18
【问题描述】:

我正在尝试使用 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(),在我知道长度 ([m]) 后,文件其余部分的最大未压缩长度为 [m] 字节,但随后我被卡住了,因为我不知道应该在子字符串中走多远才能找到下一个文件名——zlib_decode() 没有返回它在停止之前处理的压缩字节数。由于这是一种自定义格式,我似乎无法使用普通的gzopen()/gzread() 函数,因为整个文件没有被压缩(我试过了,它不起作用)。

此代码在 Delphi 中有效,因为显然您可以在普通文件读取函数和 System.ZLib 解码函数之间来回传递文件​​句柄——您可以读取 [m] 个未压缩字节,并且指针将保持在最后一个压缩byte -- 但是 PHP 似乎不支持在 read-as-normal 和 read-as-gzip 之间切换。

我在 PHP 中是否缺少一种明显的方式来处理像这样的混合内容文件格式,元数据和压缩数据以这种方式堆叠在一起?还是我不知道压缩数据长度不走运?

【问题讨论】:

    标签: php delphi gzip zlib


    【解决方案1】:

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

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

    这可行,但感觉非常hack-ish。我仍然愿意接受任何更好的方法。

    编辑:

    请注意,这最终失败了。但是,我很幸运能够提前知道预期文件名的列表,并且能够执行以下操作(更可靠,因为 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.
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-10-17
      • 1970-01-01
      • 2018-10-19
      • 1970-01-01
      • 2019-08-13
      • 1970-01-01
      • 2016-02-08
      • 1970-01-01
      相关资源
      最近更新 更多