2010-03-11 148 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