6

我正在将 Python 应用程序移植到 Android,并且在某些时候,该应用程序必须与 Web 服务通信,向其发送压缩数据。

为了做到这一点,它使用了下一个方法:

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

我正在使用下一种方法来尝试在 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);
}

但是来自服务器的 HTTP 响应不正确,我猜这是因为 Java 中的压缩结果与 Python 中的不一样。

我用 zlib.compress 和 deflate 进行了压缩“a”的小测试。

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

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

我应该如何压缩 Android 中的数据以在 Python 中获得相同的 zlib.compress() 值?

非常感谢任何帮助、指导或指针!

4

3 回答 3

7

compress 和 deflate 是不同的压缩算法,所以答案是它们不兼容。此处的差异示例是通过 Tcl 使用两种算法压缩的“a”:

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

您的 python 代码确实在压缩。并且 android 代码正在放气,但是您还获得了 UTF-8 字节顺序标记添加到 android 版本 (\xef\xbf\xbf)

您可以使用 python 发出 deflate 数据:

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'
于 2010-03-11T16:28:29.893 回答
2

尽管它们不是完全相同的算法,但它们似乎完全兼容(这意味着,例如,如果您使用 Deflater.deflate 压缩字符串,则可以使用 zlib 正确解压缩它)。

导致我出现问题的原因是 POST 中的所有表单变量都需要进行百分比转义,而 Android 应用程序没有这样做。在发送数据之前将数据编码为Base64,并在使用zlib解压缩之前修改服务器以使用Base64对其进行解码解决了这个问题。

于 2011-11-05T17:40:58.367 回答
0

byte[] input = stringToCompress.getBytes("utf-8");帮助吗?如果您的平台的默认编码不是 UTF-8,这将强制编码 String -> bytes 使用 UTF-8。此外,您创建的代码的最后一行也是如此new String- 您可能希望明确指定 UTF-8 作为解码字符集。

于 2010-03-11T13:09:18.787 回答