2010-03-11 14 views
6

Sto eseguendo il porting di un'applicazione Python su Android e, a un certo punto, questa applicazione deve comunicare con un servizio Web, inviandolo dati compressi.Are zlib.compress su Python e Deflater.deflate su Java (Android) compatibile?

Per farlo utilizza il metodo successivo:

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

Sto usando il metodo successivo per cercare di emulare questo comportamento in 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); 
} 

Ma la risposta HTTP dal il server non è corretto e immagino sia perché il risultato della compressione in Java non è uguale a quello in Python.

Ho eseguito un piccolo test comprimendo "a" entrambi con 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

Come devo comprimere i dati in Android per ottenere lo stesso valore di zlib.compress() in Python?

Qualsiasi aiuto, guida o puntatore è molto apprezzato!

+0

La riga 'return new String (compressedData);' è un bug. Non è possibile utilizzare String in questo modo. –

risposta

2

Sebbene non siano esattamente gli stessi algoritmi, sembra che siano totalmente compatibili (nel senso che se comprimi, ad esempio, una stringa utilizzando Deflater.deflate, puoi decomprimerla correttamente usando zlib).

Ciò che ha causato il mio problema era che tutte le variabili di modulo in un POST hanno bisogno di essere in percentuale di escape e l'applicazione Android non lo stava facendo. Codificare i dati su Base64 prima di inviarli e modificare il server per decodificarlo usando Base64 prima di decomprimerlo usando zlib risolto il problema.

0

byte[] input = stringToCompress.getBytes("utf-8"); help? Nel caso in cui la codifica predefinita della tua piattaforma non sia UTF-8, questo imporrà la codifica String -> byte per utilizzare UTF-8. Inoltre, lo stesso vale per l'ultima riga del codice in cui si crea un new String - si potrebbe voler specificare in modo esplicito UTF-8 come set di caratteri di decodifica.

+0

Grazie per il suggerimento! Ho intenzione di provarlo e dirti come va e anche se penso che la codifica predefinita sia già UTF-8 è sempre bene essere prudenti. –

+0

Ho provato quel suggerimento ma non ho cambiato il risultato. Grazie lo stesso! –

7

compress e deflate sono algoritmi di compressione diversi, quindi la risposta è che non saranno compatibili. Come esempio della differenza qui è 'a' compresso utilizzando i due algoritmi via Tcl: impacco

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

Il codice Python è infatti facendo. E il codice di Android sta facendo sgonfiare, ma si sta anche ottenendo il marchio UTF-8 byte order anteporre alla versione di Android (\ XEF \ XBF \ XBF)

È possibile emettere sgonfiare dati utilizzando 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 
+0

Questo è quello che sospettavo, che erano in realtà metodi di compressione diversi. Ora posso concentrarmi sulla ricerca di un modo per generare la stessa compressione di zlib.comprimere in Java (ho provato il codice Python e si sgonfia in effetti i dati come la versione di Java, ma dal momento che sto porting dell'applicazione per Android e non riesco a modificare quello originale, che stavo cercando il contrario: fare comprimere su Java). In ogni caso, risposta davvero utile finora! Ti voterei se potessi: P –

+0

+1 (ora che posso) –