Je suis en interface avec un serveur qui exige que les données qui lui sont envoyées soient compressées avec Dégonfler (codage Huffman + LZ77) et envoie également des données que je dois Gonfler .
Je sais que Python inclut Zlib, et que les bibliothèques C de Zlib prennent en charge les appels à Gonfler y Dégonfler mais ces éléments ne sont apparemment pas fournis par le module Zlib de Python. Il fournit Compresser y Décompression mais lorsque je passe un appel tel que celui-ci :
result_data = zlib.decompress( base64_decoded_compressed_string )
Je reçois l'erreur suivante :
Error -3 while decompressing data: incorrect header check
Gzip ne fait pas mieux ; lors d'un appel tel que :
result_data = gzip.GzipFile( fileobj = StringIO.StringIO( base64_decoded_compressed_string ) ).read()
Je reçois l'erreur :
IOError: Not a gzipped file
ce qui est logique puisque les données sont un Dégonflé pas un vrai fichier Gzippé archivo.
Maintenant je sais qu'il y a un Dégonfler disponible (Pyflate), mais je ne connais pas d'implémentation de la Gonfler mise en œuvre.
Il semble qu'il y ait quelques options :
- Trouver une mise en œuvre existante (idéale) de Gonfler y Dégonfler en Python
- Écrire ma propre extension Python à la bibliothèque c zlib qui inclut Gonfler y Dégonfler
- Appelez quelque chose d'autre qui peut être exécuté à partir de la ligne de commande (comme un script de Ruby, car Gonfler / Dégonfler dans zlib sont entièrement enveloppés dans Ruby)
- ?
Je suis à la recherche d'une solution, mais en l'absence de solution, je serai reconnaissant pour les idées, les opinions constructives et les idées.
Informations complémentaires : Le résultat de la déflation (et du codage) d'une chaîne de caractères devrait, pour les besoins dont j'ai besoin, donner le même résultat que le bout de code C# suivant, où le paramètre d'entrée est un tableau d'octets UTF correspondant aux données à compresser :
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;
}
L'exécution de ce code .NET pour la chaîne "deflate and encode me" donne le résultat suivant
7b0HYBxJliUmL23Ke39K9UrX4HShCIBgEyTYkEAQ7MGIzeaS7B1pRyMpqyqBymVWZV1mFkDM7Z28995777333nvvvfe6O51OJ/ff/z9cZmQBbPbOStrJniGAqsgfP358Hz8iZvl5mbV5mi1nab6cVrM8XeT/Dw==
Lorsque "deflate and encode me" est exécuté par la fonction Python Zlib.compress() puis encodé en base64, le résultat est "eJxLSU3LSSxJVUjMS1FIzUvOT0lVyE0FAFXHB6k=".
Il est clair que zlib.compress() n'est pas une implémentation du même algorithme que l'algorithme standard Deflate.
Plus d'informations :
Les 2 premiers octets des données deflate .NET ("7b0HY..."), après décodage b64 sont 0xEDBD, ce qui ne correspond pas aux données Gzip (0x1f8b), BZip2 (0x425A) ou Zlib (0x789C).
Les 2 premiers octets des données compressées Python ("eJxLS..."), après décodage b64 sont 0x789C. Il s'agit d'un en-tête Zlib.
SOLVED
Pour gérer le deflate et l'inflate brut, sans en-tête ni somme de contrôle, les choses suivantes devaient se produire :
En cas de déflation/compression : suppression des deux premiers octets (en-tête) et des quatre derniers octets (somme de contrôle).
Sur le gonflage/décompression : il y a un deuxième argument pour la taille de la fenêtre. Si cette valeur est négative, elle supprime les en-têtes. Voici mes méthodes actuelles, y compris l'encodage/décodage base64 - et elles fonctionnent correctement :
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 )