2010-03-11 14 views
6

Estoy portando una aplicación de Python a Android y, en algún momento, esta aplicación tiene que comunicarse con un servicio web y enviar datos comprimidos.¿Son compatibles zlib.compress en Python y Deflater.deflate en Java (Android)?

Con el fin de hacer que utiliza el siguiente método:

def stuff(self, data): 
    "Convert into UTF-8 and compress." 
    return zlib.compress(simplejson.dumps(data)) 

estoy usando el siguiente método para tratar de emular este comportamiento en 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); 
} 

Pero la respuesta HTTP desde el servidor no es correcto y supongo que es porque el resultado de la compresión en Java no es el mismo que el de Python.

Ejecuté una pequeña prueba para comprimir "a" con zlib.compress y desinflar.

Python, zlib.compress() -> x% 9CSJT% 02% 00% 01M% 00% A6

Android, Deflater.deflate -> H% EF% BF% BDK% 04% 00% 00b % 00b

¿Cómo debo comprimir los datos en Android para obtener el mismo valor de zlib.compress() en Python?

¡Cualquier ayuda, guía o puntero es muy apreciada!

+0

La línea 'return new String (compressedData);' es un error. No puedes usar String de esa manera. –

Respuesta

2

Aunque no son exactamente los mismos algoritmos, parece que son totalmente compatibles (lo que significa que si comprime, por ejemplo, un String usando Deflater.deflate puede descomprimirlo correctamente usando zlib).

Lo que causó mi problema fue que todas las variables de formulario en un POST deben ser por ciento escapadas, y la aplicación de Android no estaba haciendo eso. La codificación de los datos a Base64 antes de enviarlos y la modificación del servidor para decodificarlos utilizando Base64 antes de descomprimirlos usando zlib resolvió el problema.

0

¿byte[] input = stringToCompress.getBytes("utf-8"); ayuda? En caso de que la codificación predeterminada de su plataforma no sea UTF-8, esto obligará a la cadena de codificación -> bytes a usar UTF-8. Además, lo mismo ocurre con la última línea de su código donde crea un new String - es posible que desee especificar explícitamente UTF-8 como decodificador Charset.

+0

¡Gracias por su sugerencia! Voy a intentarlo y te diré cómo va, y aunque creo que la codificación predeterminada ya es UTF-8, siempre es bueno tener cuidado. –

+0

Pruebo esa sugerencia pero no cambié el resultado. ¡Gracias de todos modos! –

7

comprimir y desinflar son diferentes algoritmos de compresión por lo que la respuesta es que no serán compatibles. Como un ejemplo de la diferencia en este caso es 'a' comprimido usando los dos algoritmos a través de Tcl: compresa

% binary encode hex [zlib compress a] 
789c4b040000620062 
% binary encode hex [zlib deflate a] 
4b0400

Su código Python está haciendo de hecho. Y el código de Android está haciendo desinflarse, sin embargo, también está recibiendo la marca de orden de bytes UTF-8 colocado al comienzo de la versión de Android (\ XEF \ XBF \ XBF)

Puede emitir desinflar datos usando 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'
+0

Eso es lo que sospechaba, que en realidad eran métodos de compresión diferentes. Ahora puedo enfocarme para buscar una forma de generar la misma compresión de zlib.comprimir en Java (Probé su código Python y de hecho desinfla los datos como la versión de Java, pero como estoy transfiriendo la aplicación a Android y no puedo modificar la original, estaba buscando la inversa: comprimir en Java) De todos modos, realmente útil respuesta hasta ahora! Yo te votaría si pudiera: P –

+0

+1 (Ahora que puedo) –

Cuestiones relacionadas