2010-03-11 98 views
6

我正在將一個Python應用程序移植到Android上,並且在某種程度上,此應用程序必須與Web服務進行通信,並向其發送壓縮數據。zlib.compress是否與Java兼容的Java(Android)上的Python和Deflater.deflate?

爲了做到這一點,它使用下一個方法:

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

我用下一個方法來試圖模仿這種行爲在安卓

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); 
} 

但是從HTTP響應服務器不正確,我想這是因爲Java中的壓縮結果與Python中的壓縮結果不一樣。

我跑了一個測試壓縮「a」與zlib.compress和deflate。

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

機器人,Deflater.deflate - > H%EF%BF%BDK%04%00%00B %00b

我應該如何壓縮Android中的數據才能獲得與Python中zlib.compress()相同的值?

任何幫助,指導或指針非常感謝!

+0

行'return new String(compressedData);'是一個錯誤。你不能以這種方式使用String。 – 2011-04-03 21:22:31

回答

2

雖然他們不完全相同的算法,但它們似乎完全兼容(也就是說,如果您壓縮,例如,使用Deflater.deflate的字符串,您可以使用zlib正確解壓縮它)。

是什麼導致我的問題是POST中的所有表單變量都需要百分比轉義,而Android應用程序沒有這樣做。在發送數據之前將數據編碼爲Base64,並在使用zlib解壓之前修改服務器以使用Base64對其解碼,解決了問題。

0

請問byte[] input = stringToCompress.getBytes("utf-8");有幫助嗎?如果您的平臺的默認編碼不是UTF-8,則會強制編碼字符串 - >字節使用UTF-8。此外,對於您創建new String的代碼的最後一行也是如此 - 您可能希望明確指定UTF-8作爲解碼字符集。

+0

謝謝你的建議!我會嘗試一下,告訴你它是怎麼回事,儘管我認爲默認編碼已經是UTF-8,但總是謹慎小心。 – 2010-03-12 11:39:46

+0

我測試了這個建議,但沒有改變結果。不管怎樣,謝謝你! – 2010-03-14 18:57:52

7

壓縮和放氣是不同的壓縮算法,所以答案是他們不會兼容。由於差異的例子這裏是「A」通過Tcl使用兩種算法壓縮:壓縮

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

Python代碼確實是在做什麼。和Android的代碼是做放氣,但您也越來越前置到Android版本的UTF-8字節順序標記(\ XEF \ XBF \ XBF)

您可以使用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

這就是我所懷疑的,他們實際上是不同的壓縮方法。現在我可以專注於尋找一種方法來生成相同的zlib壓縮。使用Java壓縮(我測試了你的Python代碼,它確實減少了Java版本的數據,但是由於我將應用程序移植到Android,並且無法修改原來的應用程序,我一直在尋找其他方法:在Java上進行壓縮)。 無論如何,真正有幫助的答案迄今!如果可以的話,我會給你投票:P – 2010-03-12 13:33:12

+0

+1(現在我可以) – 2010-03-14 18:21:36