Python: inflar e esvaziar implementações
Estou interagindo com um servidor que requer que os dados enviados para ele sejam compactados comEsvaziar algoritmo (codificação Huffman + LZ77) e também envia dados que eu precisoInflar.
Eu sei que o Python inclui Zlib, e que as bibliotecas C no Zlib suportam chamadas paraInflar eEsvaziar, mas estes aparentemente não são fornecidos pelo módulo Python Zlib. Ele forneceComprimir eDescomprimir, mas quando faço uma ligação como a seguinte:
result_data = zlib.decompress( base64_decoded_compressed_string )
Eu recebo o seguinte erro:
Error -3 while decompressing data: incorrect header check
Gzip não faz melhor; ao fazer uma chamada como:
result_data = gzip.GzipFile( fileobj = StringIO.StringIO( base64_decoded_compressed_string ) ).read()
Eu recebo o erro:
IOError: Not a gzipped file
o que faz sentido como os dados é umDeflacionado arquivo não é um verdadeiroGzipado Arquivo.
Agora eu sei que existe umEsvaziar implementação disponível (Pyflate), mas eu não sei de umaInflar implementação.
Parece que existem algumas opções:
Encontre uma implementação existente (ideal) deInflar eEsvaziar em PythonEscreva minha própria extensão do Python para a biblioteca zlib c que incluiInflar eEsvaziarChame outra coisa que possa ser executada a partir da linha de comando (como um script Ruby,Inflar/Esvaziar as chamadas no zlib são totalmente agrupadas em Ruby)?Estou buscando uma solução, mas sem uma solução, ficarei grato por insights, opiniões construtivas e idéias.
Informação adicional: O resultado da deflação (e codificação) de uma string deve, para os propósitos que preciso, fornecer o mesmo resultado que o trecho a seguir do código C #, em que o parâmetro de entrada é uma matriz de bytes UTF correspondentes aos dados a serem compactados:
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;
}
A execução deste código .NET para a string "deflate and encode me" fornece o resultado
7b0HYBxJliUmL23Ke39K9UrX4HShCIBgEyTYkEAQ7MGIzeaS7B1pRyMpqyqBymVWZV1mFkDM7Z28995777333nvvvfe6O51OJ/ff/z9cZmQBbPbOStrJniGAqsgfP358Hz8iZvl5mbV5mi1nab6cVrM8XeT/Dw==
Quando "deflate e encode me" é executado através do Python Zlib.compress () e, em seguida, codificado em base64, o resultado é "eJxLSU3LSSxJVUjMS1FIzUvOT0lVyE0FAFXHB6k =".
É claro que o zlib.compress () não é uma implementação do mesmo algoritmo que o algoritmo Deflate padrão.
Mais Informações:
Os primeiros 2 bytes do .NET desinflar dados ("7b0HY ..."), após a decodificação b64 são 0xEDBD, que não corresponde aos dados Gzip (0x1f8b), dados BZip2 (0x425A) ou dados Zlib (0x789C).
Os primeiros 2 bytes dos dados comprimidos do Python ("eJxLS ..."), após a decodificação b64, são 0x789C. Este é um cabeçalho Zlib.
RESOLVIDO
Para lidar com o desinflado bruto e inflar, sem cabeçalho e soma de verificação, as seguintes coisas precisam acontecer:
Em deflate / compress: tira os dois primeiros bytes (cabeçalho) e os últimos quatro bytes (soma de verificação).
Ao inflar / descomprimir: há um segundo argumento para o tamanho da janela. Se esse valor for negativo, ele suprime os cabeçalhos. aqui estão meus métodos atualmente, incluindo a codificação / decodificação base64 - e funcionando corretamente:
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 )