如何在 UNIX 中解压缩 zlib 数据?

如何在 UNIX 中解压缩 zlib 数据?

我在 Python 中创建了 zlib 压缩数据,如下所示:

import zlib
s = '...'
z = zlib.compress(s)
with open('/tmp/data', 'w') as f:
    f.write(z)

(或外壳中的单行echo -n '...' | python2 -c 'import sys,zlib; sys.stdout.write(zlib.compress(sys.stdin.read()))' > /tmp/data:)

现在,我想在shell中解压缩数据。既不工作zcat也不uncompress工作:

$ cat /tmp/data | gzip -d -
gzip: stdin: not in gzip format

$ zcat /tmp/data 
gzip: /tmp/data.gz: not in gzip format

$ cat /tmp/data | uncompress -
gzip: stdin: not in gzip format

看来我已经创建了类似 gzip 的文件,但没有任何标头。不幸的是,我在 gzip 手册页中没有看到任何解压缩此类原始数据的选项,并且 zlib 包不包含任何可执行实用程序。

是否有实用程序可以解压缩原始 zlib 数据?

答案1

也可以使用标准解压缩它+,如果您没有或想要使用或其他工具。
诀窍是预先添加gzip幻数和压缩方法实际数据来自zlib.compress

printf "\x1f\x8b\x08\x00\x00\x00\x00\x00" |cat - /tmp/data |gzip -dc >/tmp/out

编辑:
@d0sboots 评论:对于 RAW Deflate 数据,您需要再添加 2 个空字节:
"\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\x00"

这个问题关于SO提供了有关此方法的更多信息。那里的答案表明还有一个 8 字节的页脚。

用户 @Vitali-Kushner 和 @mark-bessey 报告即使文件被截断也能成功,因此 gzip 页脚似乎并不严格要求。

@tobias-kienzler 建议使用此函数:
zlibd() (printf "\x1f\x8b\x08\x00\x00\x00\x00\x00" | cat - "$@" | gzip -dc)

答案2

zlib-flate -uncompress < IN_FILE > OUT_FILE

我尝试过这个,它对我有用。

zlib-flate可以在包中找到qpdf(根据其他答案中的评论,在 Debian Squeeze、Fedora 23 和 MacOS 上的 brew 中)

(感谢用户@tino,他在 OpenSSL 答案下方提供了此评论。制作成正确的答案以便于访问。)

答案3

我找到了一个解决方案(可能的解决方案之一),它正在使用开放式SSL:

$ openssl zlib -d < /tmp/data

或者

$ openssl zlib -d -in /tmp/data

*注意:zlib 功能显然在最近的 openssl 版本 >=1.0.0 中可用(OpenSSL 必须使用 zlib 或 zlib-dynamic 选项进行配置/构建,后者是默认值)

答案4

在 macOS 上,它是完全兼容 POSIX 的 UNIX(经过正式认证!),OpenSSL没有zlib支持,两者都没有zlib-flate,虽然第一个解决方案与所有 Python 解决方案一样有效,但第一个解决方案要求 ZIP 数据位于文件中所有其他解决方案都迫使您创建 Python 脚本。

这是一个基于 Perl 的解决方案,可以用作命令行单行程序,通过 STDIN 管道获取输入,并且可以在新安装的 macOS 上开箱即用:

cat file.compressed | perl -e 'use Compress::Raw::Zlib;my $d=new Compress::Raw::Zlib::Inflate();my $o;undef $/;$d->inflate(<>,$o);print $o;'

Perl 脚本的格式更好,如下所示:

use Compress::Raw::Zlib;
my $decompressor = new Compress::Raw::Zlib::Inflate();
my $output;
undef $/;
$decompressor->inflate(<>, $output);
print $output;

Marco d'Itri 的优化版本(见评论):

cat file.compressed | perl -MCompress::Zlib -E 'undef $/;print uncompress(<>)'

相关内容