estoy de interfaz con un servidor que requiere que los datos enviados a ella se comprime con Deflate algoritmo (codificación Huffman + LZ77) y también envía los datos que necesito Inflar.Python: inflar y desinflar implementaciones
sé que Python incluye Zlib, y que las bibliotecas de C en las llamadas de soporte Zlib a Inflar y desinflado , pero estos al parecer no son proporcionados por el módulo de Python Zlib. Sí que da Comprimir y Descomprimir , pero cuando hago una llamada tales como los siguientes:
result_data = zlib.decompress(base64_decoded_compressed_string)
recibo el siguiente error:
Error -3 while decompressing data: incorrect header check
gzip no es mejor; al realizar una llamada, tales como:
result_data = gzip.GzipFile(fileobj = StringIO.StringIO(base64_decoded_compressed_string)).read()
recibo el error:
IOError: Not a gzipped file
lo cual tiene sentido ya que los datos no es un archivo dedesinflado un verdadero archivo comprimido en GZIP .
Ahora sé que hay una desinflado aplicación disponible (Pyflate), pero no sé de una aplicacióninflado.
Parece que hay algunas opciones:
- Encuentra una implementación existente (ideal) de Inflar y desinflado en Python
- escribir mi propia extensión de Python a la zlib c biblioteca que incluye Inflar y Deflate
- Llamar a algo más que pueda ser ejecutado desde la línea de comandos (por ejemplo, un script Ruby, ya Inflar/desinflado llamadas en zlib están completamente envueltos en Rubí)
- ?
Estoy buscando una solución, pero al carecer de una solución agradeceré ideas, opiniones constructivas e ideas.
Información adicional: El resultado de desinflar (y codificación) de una cadena debe, a los efectos que necesito, dar el mismo resultado que el siguiente fragmento de código C#, donde el parámetro de entrada es una serie de bytes UTF correspondiente a los datos para comprimir:
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;
}
Ejecutando esto.código NET para la cadena "desinflar y me codificar" da el resultado
7b0HYBxJliUmL23Ke39K9UrX4HShCIBgEyTYkEAQ7MGIzeaS7B1pRyMpqyqBymVWZV1mFkDM7Z28995777333nvvvfe6O51OJ/ff/z9cZmQBbPbOStrJniGAqsgfP358Hz8iZvl5mbV5mi1nab6cVrM8XeT/Dw==
Cuando "desinflar y me codificar" se ejecuta a través de la Zlib.compress Python() y luego base64, el resultado es "eJxLSU3LSSxJVUjMS1FIzUvOT0lVyE0FAFXHB6k =" .
Está claro que zlib.compress() no es una implementación del mismo algoritmo que el algoritmo Deflate estándar.
Más información:
Los 2 primeros bytes del .NET desinflan los datos ("7b0HY ..."), después de la decodificación b64 son 0xEDBD, que no corresponde a los datos de Gzip (0x1f8b), BZip2 (0x425A) datos, o datos Zlib (0x789C).
Los primeros 2 bytes de los datos comprimidos de Python ("eJxLS ..."), después de la decodificación b64 son 0x789C. Este es un encabezado Zlib.
RESUELTO
Para manejar el deflate prima e inflar, sin cabecera y suma de comprobación, las siguientes cosas necesarias para suceden:
En deflate/compresa: tira de los dos primeros bytes (de cabecera) y la los últimos cuatro bytes (suma de comprobación).
Al inflar/descomprimir: hay un segundo argumento para el tamaño de la ventana. Si este valor es negativo, suprime los encabezados. aquí están mis métodos actualmente, incluyendo la base 64 de codificación/decodificación - y funciona correctamente:
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 Gracias por la información adicional. – Demi
@John Machin: Para responder a su primera observación ... el resultado es solo más largo en el caso de cadenas más cortas (¿encabezado? ¿Relleno?). Cuando introduzco 161 bytes de datos para deflación, antes de la codificación base64 el resultado es 126 bytes. – Demi
@John Machin: excelentes ideas e información. La firma Java de deflater utilizada es la que tiene dos parámetros, con nowrap == verdadero. Usé su ejemplo de deflactor de una línea y se infla bien en .NET y Java, a pesar de tener un aspecto diferente al valor producido al desinflarse con las bibliotecas en esos idiomas. Esto es genial. Ahora estoy trabajando en inflar - tomando los datos desinflados producidos por Java o .NET y agregando una suma de comprobación adler32 y el encabezado zlib para ver si puedo lograr que Python lo consuma bien. Te dejaré saber cómo va. – Demi