Совместимы ли zlib.compress на Python и Deflater.deflate на Java (Android)? - PullRequest
6 голосов
/ 11 марта 2010

Я портирую приложение Python на Android, и в какой-то момент это приложение должно связываться с веб-службой, отправляя сжатые данные.

Для этого используется следующий метод:

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.

Я провел небольшой тест на сжатие "a" как с помощью zlib.compress, так и сдувания.

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

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

Как мне сжать данные в Android, чтобы получить то же значение zlib.compress () в Python?

Любая помощь, руководство или указатель с благодарностью!

Ответы [ 3 ]

7 голосов
/ 11 марта 2010

сжатие и выкачивание - это разные алгоритмы сжатия, поэтому ответ будет несовместимым. В качестве примера различий здесь используется сжатие «a» с использованием двух алгоритмов через Tcl:

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

Ваш код на Python действительно выполняет сжатие. И код Android выполняет дефляцию, однако вы также получаете знак порядка байтов UTF-8, добавленный к версии для Android (\ 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'
2 голосов
/ 05 ноября 2011

Хотя они не совсем одинаковые алгоритмы, кажется, что они полностью совместимы (это означает, что если вы сжимаете, например, строку, используя Deflater.deflate, вы можете правильно распаковать ее, используя zlib).Моя проблема заключалась в том, что все переменные формы в POST должны быть экранированы в процентах, а приложение Android этого не делало.Кодирование данных в Base64 перед отправкой и изменение сервера для декодирования с использованием Base64 перед распаковкой с помощью zlib решило проблему.

0 голосов
/ 11 марта 2010

Помогает ли byte[] input = stringToCompress.getBytes("utf-8");? Если кодировка вашей платформы по умолчанию не UTF-8, это заставит кодировку String -> bytes использовать UTF-8. Также то же самое относится и к последней строке вашего кода, где вы создаете new String - вы можете явно указать UTF-8 в качестве декодирующего Charset.

...