Python: implementacje Inflate i Deflate

Łączę się z serwerem, który wymaga, aby przesyłane do niego dane były skompresowaneSiadać algorytm (kodowanie Huffmana + LZ77), a także wysyła dane, których potrzebujęNadmuchać.

Wiem, że Python zawiera Zlib i że biblioteki C w Zlib obsługują wywołaniaNadmuchać iSiadać, ale najwyraźniej nie są one dostarczane przez moduł Python Zlib. To zapewniaKompres iRozprężać, ale kiedy wykonuję połączenie, takie jak:

result_data = zlib.decompress( base64_decoded_compressed_string )

Otrzymuję następujący błąd:

Error -3 while decompressing data: incorrect header check

Gzip nie robi nic lepszego; podczas wykonywania połączenia, takiego jak:

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

Otrzymuję błąd:

IOError: Not a gzipped file

co ma sens, ponieważ dane sąDeflated plik nie jest prawdąGzipped plik.

Teraz wiem, że jestSiadać dostępna implementacja (Pyflate), ale nie wiemNadmuchać realizacja.

Wydaje się, że istnieje kilka opcji:

Znajdź istniejącą implementację (ideał)Nadmuchać iSiadać w PythonieNapisz moje własne rozszerzenie Pythona do biblioteki zlib c, która zawieraNadmuchać iSiadaćWywołaj coś innego, które można wykonać z wiersza poleceń (np. Skrypt Ruby, ponieważNadmuchać/Siadać wywołania w zlib są całkowicie zapakowane w Ruby)?

Szukam rozwiązania, ale bez rozwiązania będę wdzięczny za spostrzeżenia, konstruktywne opinie i pomysły.

Dodatkowe informacje: W wyniku deflacji (i kodowania) ciągu znaków, dla potrzeb, których potrzebuję, dać taki sam wynik, jak następujący fragment kodu C #, gdzie parametrem wejściowym jest tablica bajtów UTF odpowiadająca danym do skompresowania:

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;
}

Uruchomienie tego kodu .NET dla ciągu „deflate and encode me” daje wynik

7b0HYBxJliUmL23Ke39K9UrX4HShCIBgEyTYkEAQ7MGIzeaS7B1pRyMpqyqBymVWZV1mFkDM7Z28995777333nvvvfe6O51OJ/ff/z9cZmQBbPbOStrJniGAqsgfP358Hz8iZvl5mbV5mi1nab6cVrM8XeT/Dw==

Gdy „deflate and encode me” jest uruchamiany przez kodowanie Plix Zlib.compress () a następnie base64, wynikiem jest „eJxLSU3LSSxJVUjMS1FIzUvOT0lVyE0FAFXHB6k =”.

Jasne jest, że zlib.compress () nie jest implementacją tego samego algorytmu, co standardowy algorytm Deflate.

Więcej informacji:

Pierwsze 2 bajty danych deflacji .NET („7b0HY ...”) po dekodowaniu b64 to 0xEDBD, które nie odpowiadają danym Gzip (0x1f8b), danych BZip2 (0x425A) lub danych Zlib (0x789C).

Pierwsze 2 bajty skompresowanych danych Pythona („eJxLS ...”) po dekodowaniu b64 to 0x789C. To jest nagłówek Zlib.

ROZWIĄZANY

Aby obsłużyć surową deflację i nadmuchać, bez nagłówka i sumy kontrolnej, należy wykonać następujące czynności:

W deflate / compress: usuń pierwsze dwa bajty (nagłówek) i ostatnie cztery bajty (sumę kontrolną).

Po nadmuchaniu / dekompresji: istnieje drugi argument dotyczący rozmiaru okna. Jeśli ta wartość jest ujemna, pomija nagłówki. oto moje metody obecnie, w tym kodowanie / dekodowanie base64 - i działające poprawnie:

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 )

questionAnswers(2)

yourAnswerToTheQuestion