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!

Foi útil?

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.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top