首页 > 解决方案 > 如何使用zlib python从未压缩的字符串中取回压缩字符串?

问题描述

我有一个"H4sIAAAAAAAEACtmyGBIZMhjKAHTALXiaIAOAAAA"由 C# 代码生成的压缩字符串。我尝试使用 zlib 解压缩,如下所示:

c = zlib.decompress(base64.b64decode("H4sIAAAAAAAEACtmyGBIZMhjKAHTALXiaIAOAAAA"), 16 + zlib.MAX_WBITS)
print(c)
print(c.decode('utf-8'))

上述代码片段的输出是:shantha

现在,如何使用 zlib"H4sIAAAAAAAEACtmyGBIZMhjKAHTALXiaIAOAAAA"从原始字符串中取回压缩字符串?"shantha"

编辑:创建压缩字符串的 C# 代码:

using System.IO;
using System;
using System.IO.Compression;
using System.Text;

public class Program
{
    public static void Main(string[] args)
    {

        string plainText = "shantha";
        byte[] buffer = Encoding.UTF8.GetBytes(plainText);  
        var memoryStream = new MemoryStream();

        using (var gZipStream = new GZipStream(memoryStream, compressionMode.Compress, true))
        {
            gZipStream.Write(buffer, 0, buffer.Length);
        }
        memoryStream.Position = 0;
        var compressedData = new byte[memoryStream.Length];
        memoryStream.Read(compressedData, 0, compressedData.Length);
        var gZipBuffer = new byte[compressedData.Length];
        Buffer.BlockCopy(compressedData, 0, gZipBuffer, 0, compressedData.Length);
        Console.WriteLine(Convert.ToBase64String(gZipBuffer));
    }
}

标签: c#python-3.xzlib

解决方案


这不是“山塔”。Base-64 编码的 zlib 流解码为b"s\0h\0a\0n\0t\0h\0a\0". 有一堆空值散布在打印时不显示的字符。(根据 Hampus 的评论,这可能是由于在压缩之前将字符串编码为 UTF-16。)

您的原始字符串是 gzip 编码的,而不是 zlib。所以你需要使用zlib.compressobjwithwbits=31来生成 zlib 格式。示例,包括编码为 UTF-16、little-endian,输入交互式 Python:

>>> import zlib
>>> import base64
>>> s = "shantha".encode('utf-16le')
>>> z = zlib.compressobj(wbits=31)
>>> c = z.compress(s)
>>> c += z.flush(zlib.Z_FINISH)
>>> base64.b64encode(c)
b'H4sIAAAAAAAAEytmyGBIZMhjKAHTALXiaIAOAAAA'

生成的 gzip 标头可能会略有不同,就像这里一样,取决于您运行的操作系统和压缩级别。同样对于较大的输入和其他压缩级别或软件版本,压缩数据也可能会有所不同。但这没关系。重要的是在解压缩时可以取回原始数据。


推荐阅读