sto interfacciamento con un server che richiede che i dati inviati ad esso è compresso con Deflate algoritmo (codifica di Huffman + LZ77) e invia i dati che ho bisogno di Gonfiare.Python: gonfiare e sgonfiare le implementazioni
So che Python include Zlib, e che le librerie C di chiamate di assistenza Zlib a Gonfiare e Sgonfiare, ma questi a quanto pare non sono forniti dal modulo Python zlib. Esso fornisce Comprimere e decomprimere, ma quando faccio una chiamata come la seguente:
result_data = zlib.decompress(base64_decoded_compressed_string)
ricevo il seguente errore:
Error -3 while decompressing data: incorrect header check
Gzip non fa meglio; quando si effettua una chiamata come ad esempio:
result_data = gzip.GzipFile(fileobj = StringIO.StringIO(base64_decoded_compressed_string)).read()
ricevo l'errore:
IOError: Not a gzipped file
che ha un senso in quanto i dati è un Sgonfiato non file di un vero e proprio Gzipped file.
Ora so che c'è un Sgonfiare implementazione disponibili (Pyflate), ma non so di un implementazione Inflate.
Sembra che ci sono alcune opzioni:
- Trova un'implementazione esistente (ideale) di Gonfiate e Sgonfiare in Python
- scrivere il mio estensione Python al zlib c libreria che include Gonfia e Deflate
- Chiama qualcos'altro che può essere eseguito dalla riga di comando (ad esempio uno script rubino, poiché gonfiare/Deflate chiamate in zlib sono completamente avvolti in rubino)
- ?
Sto cercando una soluzione, ma senza una soluzione sarò grato per intuizioni, opinioni costruttive e idee.
Ulteriori informazioni: Il risultato di sgonfiamento (e codifica) una stringa dovrebbe, ai fini ho bisogno, dare lo stesso risultato come il seguente frammento di codice C#, in cui il parametro di ingresso è un array di byte UTF corrispondente ai dati da comprimere:
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;
}
Esecuzione di questo.NET codice per la stringa "sgonfiare e mi codificare" dà il risultato
7b0HYBxJliUmL23Ke39K9UrX4HShCIBgEyTYkEAQ7MGIzeaS7B1pRyMpqyqBymVWZV1mFkDM7Z28995777333nvvvfe6O51OJ/ff/z9cZmQBbPbOStrJniGAqsgfP358Hz8iZvl5mbV5mi1nab6cVrM8XeT/Dw==
Quando "sgonfiare e mi codificare" è gestito attraverso il Python Zlib.compress() e poi codificato Base64, il risultato è "eJxLSU3LSSxJVUjMS1FIzUvOT0lVyE0FAFXHB6k =" .
È chiaro che zlib.compress() non è un'implementazione dello stesso algoritmo dell'algoritmo Deflate standard.
Ulteriori informazioni:
I primi 2 byte del NET sgonfiano dati ("7b0HY ..."), dopo la decodifica b64 sono 0xEDBD, che non corrisponde ai dati Gzip (0x1f8b), BZip2 (0x425A) dati o dati Zlib (0x789C).
I primi 2 byte dei dati compressi Python ("eJxLS ..."), dopo la decodifica b64 sono 0x789C. Questa è un'intestazione Zlib.
risolto
Per gestire la sgonfiare grezzo e gonfiare, senza intestazione e checksum, le seguenti cose necessarie accadano:
On deflate/compressa: nudo i primi due byte (intestazione) e la ultimi quattro byte (checksum).
Su gonfia/decompressione: esiste un secondo argomento per la dimensione della finestra. Se questo valore è negativo, sopprime le intestazioni. qui sono i miei metodi attualmente, tra cui la codifica Base64/decodifica - e funziona correttamente:
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)
+1 Grazie per le informazioni aggiuntive. – Demi
@John Machin: Per rispondere alla tua prima osservazione ... il risultato è solo più lungo nel caso di stringhe più corte (intestazione? Padding?). Quando inserisco 161 byte di dati per la deflazione, prima della codifica base64 il risultato è 126 byte. – Demi
@John Machin: grandi approfondimenti e informazioni. La firma Java del deflater utilizzato è quella con due parametri, con nowrap == true. Ho usato il tuo esempio di deflattore a una riga e si gonfia bene in .NET e Java, nonostante sia diverso dal valore prodotto deflazionandosi con le librerie in quelle lingue. È grandioso Ora sto lavorando per gonfiare - prendendo i dati sgonfiati prodotti da Java o .NET e aggiungendo un checksum adler32 e l'intestazione zlib per vedere se riesco a far sì che Python lo consumi bene. Ti farò sapere come va. – Demi