Это как zlib.сжатие на Python и дефлятор.выкачать на Java (Android) совместимый?

Я портирую приложение 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 не такой же, как в Питон.

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

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

Андроид, Deflater.сдуть - > H%EF%BF%BDK%04%00%00b % 00b

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

любая помощь, наведение или указатель больш оценены!

3 ответов


сжатие и сдувание-это разные алгоритмы сжатия, поэтому ответ заключается в том, что они не будут совместимы. В качестве примера разницы здесь " 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'

хотя они не совсем те же алгоритмы, кажется, что они полностью совместимы (это означает, что если вы сжимаете, например, строку с помощью дефлятора.deflate вы можете правильно распаковать его, используя zlib).

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


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