Python 上的 zlib.compress 和 Java (Android) 上的 Deflater.deflate 是否兼容?

发布于 2024-08-24 08:12:17 字数 1834 浏览 10 评论 0原文

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

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

I am porting a Python application to Android and, at some point, this application has to communicate with a Web Service, sending it compressed data.

In order to do that it uses the next method:

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

I am using the next method to try to emulate this behavior 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);
}

But the HTTP response from the server is not correct and I guess it is because the result of the compression in Java is not the same as the one in Python.

I ran a little test compressing "a" both with zlib.compress and deflate.

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

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

How should I compress the data in Android to obtain the same value of zlib.compress() in Python?

Any help, guidance or pointer is greatly appreciated!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

羁〃客ぐ 2024-08-31 08:12:17

compress 和 deflate 是不同的压缩算法,因此答案是它们不兼容。作为差异的一个例子,这里是通过 Tcl 使用两种算法压缩“a”:

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

您的 python 代码确实在进行压缩。 Android 代码正在执行 deflate,但是您还获得了 Android 版本前面的 UTF-8 字节顺序标记 (\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'

compress and deflate are different compression algorithms so the answer is they will not be compatible. As an example of the difference here is 'a' compressed using the two algorithms via Tcl:

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

Your python code is indeed doing compress. And the android code is doing deflate, however you are also getting the UTF-8 byte order mark prepended to the android version (\xef\xbf\xbf)

You can emit deflate data using 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'
剩余の解释 2024-08-31 08:12:17

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

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

Although they are not exactly the same algorithms, it seems that they are totally compatible (meaning that if you compress, for example, an String using Deflater.deflate you can correctly uncompress it using zlib).

What caused my problem was that all form variables in a POST need to be percent escaped, and the Android application was not doing that. Encoding the data to Base64 before sending it, and modifying the server to decode it using Base64 before uncompressing it using zlib solved the problem.

窝囊感情。 2024-08-31 08:12:17

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

Does byte[] input = stringToCompress.getBytes("utf-8"); help? In case your platform's default encoding is not UTF-8, this will force the encoding String -> bytes to use UTF-8. Also, the same goes for the last line of your code where you create a new String - you may want to explicitly specify UTF-8 as the decoding Charset.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文