我有一个流程,其中某些数据(例如图像/视频)使用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错误。
在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] 删除。
我来说两句