在C#中使用GZIP压缩并在python中解压缩失败

卡米洛·特雷文托(Camilo Terevinto)

我有一个流程,其中某些数据(例如图像/视频)使用GZip压缩,如下所示:

await using var outputStream = new MemoryStream();
await using var compressionStream = new GZipStream(outputStream, CompressionMode.Compress);

await compressionStream.WriteAsync(payload);
await compressionStream.FlushAsync();

outputStream.Position = 0;
return outputStream.ToArray()

上面的代码不是我的团队提供的,但是可以根据需要进行更改。

如果我将输出转换成base64字符串并使用此简单代码测试将其解压缩,则可以正常工作:

var bytes = Convert.FromBase64String("H4sIAAAAAAAACirOz01VKEmtKAEAAAD//w=="); // "some text"
using var ms = new MemoryStream(bytes);
using var ds = new GZipStream(ms, CompressionMode.Decompress);
using var output = new MemoryStream();
ds.CopyTo(output);
ds.Flush();

var result = output.ToArray();

但是,我的要求是在python脚本中获取压缩的有效负载,并在将其传递到另一个系统之前对其进行解压缩。我对python一点都不熟悉,所以我做了一个非常简单的脚本:

import base64
import gzip

encodedBase64 = "H4sIAAAAAAAACirOz01VKEmtKAEAAAD//w=="
decodedBytes = base64.standard_b64decode(encodedBase64)
decompressedBytes = gzip.decompress(decodedBytes)

上面的失败与: EOFError: Compressed file ended before the end-of-stream marker was reached

我当然进行了研究,发现了类似这样的问答,但没有任何帮助(例如,使用该答案失败gzip.BadGzipFile: Not a gzipped file (b'\x00\x00')。其他尝试产生了不同的gzip错误。

广州7

GzipStream需要你读它的输出之前处置。Gzip有一个页脚,需要将其添加到流的末尾,并且通过Dispose()(也通过Close())(而不是通过Flush()添加我想这很有意义,因为Flush()在编码过程中可能会多次调用它,所以添加页脚将是错误的位置。

我重写了您的代码以将对象放置在适当的位置,并且async由于您正在处理纯同步操作,因此也摆脱了它

public static string Encode()
{
    var payload = Encoding.ASCII.GetBytes("some text");
    using (var outputStream = new MemoryStream())
    {
        using (var compressionStream = new GZipStream(outputStream, CompressionMode.Compress))
        {
            compressionStream.Write(payload);
        }
        var result = outputStream.ToArray();
        return Convert.ToBase64String(result);
    }   
}

这产生输出

H4sIAAAAAAAAAyvOz01VKEmtKAEAur26TwkAAAA=

它比您看到的输出稍长,表明它包含Python期望的页脚。至少在.NET中,它仍会解码为相同的结果。

有趣的GzipStream,.NET对于缺少页脚具有强大的功能,但Python版本不支持。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章