在Python中发送压缩的zip存档文件时出现问题,但在Rust中尝试解压缩时出现问题

2024-10-02 12:24:31 发布

您现在位置:Python中文网/ 问答频道 /正文

我有这段代码,它用Python中的zlibgzip)压缩数据

dta = bytes(str("..."))
res = zlib.compress(dta)
with open('packed.gz', 'wb') as f:
    f.write(t)

我想把它锈开

use std::io::prelude::*;
use flate2::read::GzDecoder; // flate2 = "1.0"
use std::fs::File;

fn main() {
    let f = File::open("packed.gz").unwrap();
    let mut d = GzDecoder::new(f);
    let mut s = String::new();
    d.read_to_string(&mut s).unwrap();
    println!("{}", s);
}

我得到

thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: Custom { kind: InvalidInput, error: "invalid gzip header" }', src/main.rs:11:30

文件格式的差异是否有问题


Tags: readusemainopenunwrapstdletgz
3条回答

确实zlib压缩是gzip兼容的,正如python stdlib documentation所提到的。这是因为zlib和gzip都使用deflate压缩标准

zlib生成原始的deflate压缩字节流。另一方面gzip是单次压缩的标准,它将压缩流包裹在放气上。因此,如果从gzip文件中去掉文件头,可以使用原始deflate库进行解压缩

字符串This is the raw stringzlib压缩流如下所示

>>> import zlib
>>> data = bytes(str("This is the raw string"), encoding="utf-8")
>>> res = zlib.compress(data)
>>> print(res)
b'x\x9c\x0b\xc9\xc8,V\x00\xa2\x92\x8cT\x85\xa2\xc4r\x85\xe2\x92\xa2\xcc\xbct\x00ZI\x08\x17'

这是(当您将其发送到xxd时)

00000000: 789c 0bc9 c82c 5600 a292 8c54 85a2 c472  x....,V....T...r
00000010: 85e2 92a2 ccbc 7400 5a49 0817            ......t.ZI..

前2个字节声明文件的类型

78 01 - No Compression/low
78 9C - Default Compression
78 DA - Best Compression 

在我们的例子中,它是78 9C,它是zlib,带有默认压缩,这是python在其文档中所说的

file package.gz

它应该是zlib compressed data,因为这就是文件头的样子

如果我们尝试使用gzip进行压缩,让我们看看会出现什么

>>> import gzip
>>> data = bytes(str("This is the raw string"), encoding="utf-8")
>>> gzip.compress(data)
b'\x1f\x8b\x08\x00\xd6\x1bw_\x02\xff\x0b\xc9\xc8,V\x00\xa2\x92\x8cT\x85\xa2\xc4r\x85\xe2\x92\xa2\xcc\xbct\x00&\x91\x1a\x82\x16\x00\x00\x00'

如果你注意到十六进制转储

00000000: 1f8b 0800 d61b 775f 02ff 0bc9 c82c 5600  ......w_.....,V.
00000010: a292 8c54 85a2 c472 85e2 92a2 ccbc 7400  ...T...r......t.
00000020: 2691 1a82 1600 0000                      &.......

神奇的数字显示为:1f 8bwiki)。如果您查看头部,您将看到两个十六进制转储包含相同的压缩数据,这是 对于zlib

00000000: .... 0bc9 c82c 5600 a292 8c54 85a2 c472  x....,V....T...r
00000010: 85e2 92a2 ccbc 7400 .... ....            ......t.ZI..

还有,对于gzip

00000000: .... .... .... .... .... 0bc9 c82c 5600  ......w_.....,V.
00000010: a292 8c54 85a2 c472 85e2 92a2 ccbc 7400  ...T...r......t.
00000020: .... .... .... ....                      &.......

因此,如果你ask rust to use the correct decoder,它肯定会起作用。这就是标准的好处

因此,gzip只是zlib容器上的一个容器,我没有解释hextump中其他字节的含义(因为我还没有查找它)

python程序生成的数据流实际上不是.gz文件,而是原始的DEFLATE流。如果需要.gz文件(包括flate2::read::GzDecoder需要的gz头),请使用Python中的gzip模块。如果确实需要原始的DEFLATE流(由zlib.compress生成),请使用flate2::read::DeflateDecoder解压缩数据

结果是flate2中有ZlibDecoder。。。它是有效的

相关问题 更多 >

    热门问题