65

サーバーに送信されるデータがDeflateアルゴリズム (ハフマン エンコーディング + LZ77) で圧縮されている必要があり、 Inflateに必要なデータも送信するサーバーとインターフェイスしています。

Python には Zlib が含まれており、Zlib の C ライブラリはInflateDeflateの呼び出しをサポートしていることは知っていますが、これらは明らかに Python Zlib モジュールでは提供されていません。CompressDecompressを提供しますが、次のような呼び出しを行うと:

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 ファイルではなく、Deflatedファイルであるため、これは理にかなっています。

利用可能なDeflate実装 (Pyflate) があることはわかっていますが、 Inflate実装については知りません。

いくつかのオプションがあるようです:

  1. PythonでInflateDeflateの既存の実装 (理想) を見つける
  2. InflateDeflateを含む zlib c ライブラリに独自の Python 拡張機能を記述します。
  3. コマンドラインから実行できる何かを呼び出します (zlib のInflate / Deflate呼び出しは Ruby で完全にラップされているため、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 データ ("7b0HY...") の最初の 2 バイトは 0xEDBD であり、Gzip データ (0x1f8b)、BZip2 (0x425A) データ、または Zlib (0x789C) データに対応しません。

b64 デコード後の Python 圧縮データ (「eJxLS...」) の最初の 2 バイトは 0x789C です。これは Zlib ヘッダーです。

解決した

ヘッダーとチェックサムなしで生のデフレートとインフレートを処理するには、次のことが必要です。

デフレート/圧縮時: 最初の 2 バイト (ヘッダー) と最後の 4 バイト (チェックサム) を取り除きます。

inflate/decompress: ウィンドウ サイズの 2 番目の引数があります。この値が負の場合、ヘッダーは抑制されます。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 )
4

2 に答える 2