【问题标题】:Are zlib.compress on Python and Deflater.deflate on Java (Android) compatible?Python 上的 zlib.compress 和 Java (Android) 上的 Deflater.deflate 是否兼容?
【发布时间】:2011-01-26 08:47:07
【问题描述】:

我正在将一个 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()相同的值?

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

【问题讨论】:

  • return new String(compressedData); 行是一个错误。你不能那样使用字符串。

标签: java python android zlib deflate


【解决方案1】:

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'

【讨论】:

  • 这就是我的怀疑,它们实际上是不同的压缩方法。现在我可以集中精力寻找一种在 Java 中生成与 zlib.compress 相同的压缩的方法(我测试了你的 Python 代码,它确实像 Java 版本一样压缩数据,但是由于我将应用程序移植到 Android 并且我无法修改原来的,我正在寻找另一种方式:在Java上进行压缩)。无论如何,到目前为止真的很有帮助!如果可以的话,我会投票给你:P
【解决方案2】:

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

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

【讨论】:

    【解决方案3】:

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

    【讨论】:

    • 感谢您的建议!我将尝试它并告诉你它是如何进行的,虽然我认为默认编码已经是 UTF-8,但要小心谨慎。
    • 我测试了这个建议,但没有改变结果。还是谢谢你!
    猜你喜欢
    • 2015-02-23
    • 2018-08-18
    • 1970-01-01
    • 1970-01-01
    • 2010-12-22
    • 2023-04-01
    • 1970-01-01
    • 2018-05-18
    • 1970-01-01
    相关资源
    最近更新 更多