我在 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
也可以使用标准解压缩它shell脚本+压缩包,如果您没有或想要使用开放式SSL或其他工具。
诀窍是预先添加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 建议使用此函数bashrc:
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(<>)'