python教程—Python:膨胀和收缩实现-Python实用宝典

python教程—Python:膨胀和收缩实现

我正在与一个服务器接口,它要求发送给它的数据使用Deflate算法(Huffman encoding + LZ77)进行压缩,并发送我需要膨胀的数据。

我正在与一个服务器接口,该服务器要求发送到它的数据使用Deflate算法(Huffman encoding + LZ77)进行压缩,并发送我需要的数据来充气

我知道Python包含Zlib,而且Zlib中的C支持调用充气充气,但这些显然不是Python Zlib模块提供的。它确实提供了压缩解压,但是当我进行如下调用时:

    result_data = zlib.decompress( base64_decoded_compressed_string )

我收到以下错误:

    Error -3 while decompressing data: incorrect header check

Gzip也好不到哪里去;打电话时,例如:

    result_data = gzip.GzipFile( fileobj = StringIO.StringIO( base64_decoded_compressed_string ) ).read()

我收到错误:

    IOError: Not a gzipped file

这是有意义的,因为数据是一个压缩的文件,而不是一个真正的 gzip压缩的文件。

现在我知道有一个可用的Deflate实现(Pyflate),但是我不知道有一个通货膨胀实现。

似乎有几个选择:

  1. 在Python中找到一个现有的充气充气的实现(理想)
  2. 编写我自己的Python扩展到zlib c,其中包括充气充气
  3. 调用可以从命令行执行的其他东西(例如Ruby脚本,因为充气/收缩调用在zlib中被完全封装在Ruby中)
  4. 吗?

我正在寻找一个解决方案,但是如果没有一个解决方案,我将感谢我的洞察力、建设性的意见和想法。

<强> < /强>附加信息:
出于我需要的目的,压缩(和编码)字符串的结果应该与下面的c#代码片段给出相同的结果,其中输入参数是与要压缩的数据对应的UTF字节数组:

    public static string DeflateAndEncodeBase64(byte[] data) { if (null == data || data.Length < 1) return null; string compressedBase64 = ""; //write into a new memory stream wrapped by a deflate stream using (MemoryStream ms = new MemoryStream()) { using (DeflateStream deflateStream = new DeflateStream(ms, CompressionMode.Compress, true)) { //write byte buffer into memorystream deflateStream.Write(data, 0, data.Length); deflateStream.Close(); //rewind memory stream and write to base 64 string byte[] compressedBytes = new byte[ms.Length]; ms.Seek(0, SeekOrigin.Begin); ms.Read(compressedBytes, 0, (int)ms.Length); compressedBase64 = Convert.ToBase64String(compressedBytes); } } return compressedBase64; }

运行字符串“deflate and encode me”的.NET代码将得到结果

    7b0HYBxJliUmL23Ke39K9UrX4HShCIBgEyTYkEAQ7MGIzeaS7B1pRyMpqyqBymVWZV1mFkDM7Z28995777333nvvvfe6O51OJ/ff/z9cZmQBbPbOStrJniGAqsgfP358Hz8iZvl5mbV5mi1nab6cVrM8XeT/Dw==

当通过Python Zlib.compress()运行“deflate and encode me”,然后对base64进行编码时,结果是“eJxLSU3LSSxJVUjMS1FIzUvOT0lVyE0FAFXHB6k=”。

显然,zlib.compress()不是与标准Deflate算法相同的算法的实现。

<强> < /强>的更多信息:

在b64解码之后,. net deflate data(“7b0HY…”)的前2个字节是0xEDBD,它不对应于Gzip数据(0x1f8b)、BZip2 (0x425A)或Zlib (0x789C)数据。

在b64解码之后,Python压缩数据的前2个字节(“eJxLS…”)是0x789C。这是一个Zlib头。

<强> < /解决强>

要处理原始通货紧缩和通货膨胀,没有标题和校验和,需要做以下事情:

压缩:去掉前两个字节(头)和后四个字节(校验和)。

关于膨胀/解压:窗口大小还有第二个参数。如果该值为负,则会抑制header。以下是我目前的方法,包括base64编码/解码-和正常工作:

    import zlib import base64 def decode_base64_and_inflate( b64string ): decoded_data = base64.b64decode( b64string ) return zlib.decompress( decoded_data , -15) def deflate_and_base64_encode( string_val ): zlibbed_str = zlib.compress( string_val ) compressed_string = zlibbed_str[2:-4] return base64.b64encode( compressed_string )

回答

这是对MizardX的回答的补充,给出了一些解释和背景。

参见http://www.chiramattel.com/george/blog/2007/09/09/deflatestream-block-length does-not-match.html

根据RFC 1950,以默认方式构造的zlib流由:

  • 2字节头(例如0x78 0x9C)
  • a deflate stream—参见RFC 1951
  • 未压缩数据的一个Adler-32校验和(4字节)

c# DeflateStream在(您猜对了)一个deflate流上工作。MizardX的代码告诉zlib模块,数据是原始的压缩流。

观察:(1)希望c#“通货紧缩”方法产生一个较长的字符串只发生在输入较短的情况下(2)使用原始的通货紧缩流而不使用Adler-32校验和?有点冒险,除非换成更好的。

<强> < /强>更新

<强>错误消息块长度与其补码不匹配

如果您试图使用c# DeflateStream膨胀一些压缩数据,并且您得到了该消息,那么很有可能您给了它一个zlib流,而不是一个deflate流。

请参见如何对文件的一部分使用DeflateStream ?

还可以将错误消息复制/粘贴到谷歌搜索中,您将得到许多相同的结果(包括这个答案前面的那个)。

Java Deflater…“本网站”使用…c# DeflateStream“非常简单,并且已经针对Java实现进行了测试”。网站使用下列哪一个可能的Java平减器构造函数?

公共平减器(int级,布尔nowrap)

使用指定的压缩级别创建新的压缩器。如果“nowrap”为真,那么为了支持GZIP和PKZIP中使用的压缩格式,将不使用ZLIB头和校验和字段。

公共紧缩(int)

使用指定的压缩级别创建新的压缩器。压缩数据将以ZLIB格式生成。

公共紧缩()

创建具有默认压缩级别的新压缩器。压缩数据将以ZLIB格式生成。

:

    uncompressed_string.encode('zlib')[2:-4] # does not work in Python 3.x

    zlib.compress(uncompressed_string)[2:-4]

​Python实用宝典 (pythondict.com)
不只是一个宝典
欢迎关注公众号:Python实用宝典

本文由 Python实用宝典 作者:Python实用宝典 发表,其版权均为 Python实用宝典 所有,文章内容系作者个人观点,不代表 Python实用宝典 对观点赞同或支持。如需转载,请注明文章来源。
1

发表评论