Zlib.compress em Python e Deflater.deflate em Java (Android) são compatíveis?
Pergunta
Estou portando uma aplicação Python para Android e, em algum momento, esta aplicação terá que se comunicar com um Web Service, enviando-lhe dados compactados.
Para fazer isso, ele usa o próximo método:
def stuff(self, data):
"Convert into UTF-8 and compress."
return zlib.compress(simplejson.dumps(data))
Estou usando o próximo método para tentar emular esse comportamento no Android:
private String compressString(String stringToCompress)
{
Log.i(TAG, "Compressing String " + stringToCompress);
byte[] input = stringToCompress.getBytes();
// Create the compressor with highest level of compression
Deflater compressor = new Deflater();
//compressor.setLevel(Deflater.BEST_COMPRESSION);
// Give the compressor the data to compress
compressor.setInput(input);
compressor.finish();
// Create an expandable byte array to hold the compressed data.
// You cannot use an array that's the same size as the orginal because
// there is no guarantee that the compressed data will be smaller than
// the uncompressed data.
ByteArrayOutputStream bos = new ByteArrayOutputStream(input.length);
// Compress the data
byte[] buf = new byte[1024];
while (!compressor.finished())
{
int count = compressor.deflate(buf);
bos.write(buf, 0, count);
}
try {
bos.close();
} catch (IOException e)
{
}
// Get the compressed data
byte[] compressedData = bos.toByteArray();
Log.i(TAG, "Finished to compress string " + stringToCompress);
return new String(compressedData);
}
Mas a resposta HTTP do servidor não está correta e acho que é porque o resultado da compactação em Java não é o mesmo do Python.
Fiz um pequeno teste compactando "a" com zlib.compress e deflate.
Python, zlib.compress() -> x%9CSJT%02%00%01M%00%A6
Android, Deflater.deflate -> H%EF%BF%BDK%04%00%00b%00b
Como devo compactar os dados no Android para obter o mesmo valor de zlib.compress() em Python?
Qualquer ajuda, orientação ou indicação é muito apreciada!
Solução 2
Embora não sejam exatamente os mesmos algoritmos, parece que são totalmente compatíveis (o que significa que se você compactar, por exemplo, uma String usando Deflater.deflate você pode descompactá-la corretamente usando zlib).
O que causou meu problema foi que todas as variáveis de formulário em um POST precisavam ter escape percentual, e o aplicativo Android não estava fazendo isso.Codificar os dados para Base64 antes de enviá-los e modificar o servidor para decodificá-los usando Base64 antes de descompactá-los usando zlib resolveu o problema.
Outras dicas
Compressa e deflam são algoritmos de compressão diferentes, então a resposta é que eles não serão compatíveis. Como exemplo da diferença aqui é 'a' comprimido usando os dois algoritmos via TCL:
% binary encode hex [zlib compress a]
789c4b040000620062
% binary encode hex [zlib deflate a]
4b0400
Seu código Python está realmente fazendo compactação. E o código do Android está fazendo esvaziar, no entanto, você também está recebendo a marca de ordem do UTF-8 bytes presa à versão Android ( xef xbf xbf)
Você pode emitir dados de esvaziar usando o Python:
def deflate(data):
zobj = zlib.compressobj(6,zlib.DEFLATED,-zlib.MAX_WBITS,zlib.DEF_MEM_LEVEL,0)
zdata = zobj.compress(data)
zdata += zobj.flush()
return zdata
>>> deflate("a")
'K\x04\x00'
Faz byte[] input = stringToCompress.getBytes("utf-8");
ajuda? Caso a codificação padrão da sua plataforma não seja UTF-8, isso forçará a sequência de codificação-> bytes a usar o UTF-8. Além disso, o mesmo vale para a última linha do seu código em que você cria um new String
- Você pode especificar explicitamente o UTF-8 como o charset de decodificação.