Является ли Android InflaterInputStream таким же, как популярная библиотека ZLIB для Windows?

#java #android #zlib #deflate #jzlib

#java #Android #zlib #deflate #jzlib

Вопрос:

Я пытаюсь распаковать данные, которые были сжаты с использованием библиотеки ZLIB, написанной Жан-Лу Гайи еще в 1990-х годах. Я думаю, что это популярная библиотека (я вижу много программ, которые отправляют zlib32.dll файл, который он использует) поэтому я надеюсь, что кто-то будет достаточно знаком с этим, чтобы помочь мне. Я использую функцию compress () напрямую, которая, судя по тому, что я прочитал, использует формат DEFLATE rfc-1951.

Вот фрагмент кода, который я использую для чтения некоторых сжатых данных из потока и их распаковки:

 InputStream is = new ByteArrayInputStream(buf);

//GZIPInputStream gzis = new GZIPInputStream(is);

InflaterInputStream iis = new InflaterInputStream(is);

byte[] buf2 = new byte[uncompressedDataLength];

iis.read(buf2);
  

Функция iis.read (buf2) выдает внутреннее исключение «Ошибка формата данных». Я также пытался использовать GZIPInputStream, но это также выдает то же исключение.

Переменная «buf» имеет тип byte[], и я подтвердил путем отладки, что она совпадает с тем, что моя программа C возвращает из функции ZLIB compress () (фактические данные поступают с сервера по TCP). «uncompressedDataLength» — это известный размер несжатых данных, который также был предоставлен программой C (сервером).

Кто-нибудь пробовал читать / записывать данные с помощью этой библиотеки, а затем читать / записывать те же данные на Android с использованием Java?

Я нашел «чистый Java-порт ZLIB», на который ссылаются в нескольких местах, и, если мне нужно, я могу попробовать это, но я бы предпочел использовать встроенные функции / OS, если это возможно.

Ответ №1:

Используемые здесь форматы данных deflate, zlib и gzip взаимосвязаны.

  • В основе лежит формат сжатых данных deflate, определенный в RFC 1951. Поскольку в чистом виде он часто совершенно бесполезен, мы обычно используем формат переноса вокруг него.

  • Формат сжатых данных gzip (RFC 1952) предназначен для сжатия файлов. Он состоит из заголовка, в котором есть место для имени файла и некоторых атрибутов, потока данных deflate и контрольной суммы CRC-32 (4 байта) в конце. (В спецификации также есть поддержка нескольких таких файлов в одном потоке, но я думаю, что это используется не так часто.)

  • Формат сжатых данных zlib, определенный в RFC 1950: Он состоит из заголовка меньшего размера (2 или 6 байт), потока данных deflate и контрольной суммы Adler-32 (4 байта) в конце. (Предполагается, что контрольная сумма Adler-32 вычисляется быстрее, чем контрольная сумма CRC-32, используемая в gzip.) Он предназначен для сжатой передачи данных внутри некоторых других протоколов или для сжатого хранения внутри других форматов файлов. Например, он используется внутри формата файла PNG.

Библиотека zlib поддерживает все эти форматы. Java-это java.util.zip построен на zlib (как часть реализации виртуальной машины / собственных вызовов) и предоставляет доступ к ним с помощью нескольких классов:

  • Классы Deflater и Inflater реализуют — в зависимости от nowrap аргумента конструктора — либо форматы данных zlib, либо deflate.

  • DeflaterOutputStream / DeflaterInputStream/inflateriputstream / InflaterOutputStream построен на Deflater / надувателе. В документации четко не указано, реализует ли Inflater / Deflater по умолчанию zlib или deflate, но источник показывает, что он использует конструктор по умолчанию Deflater or Inflater , который реализует zlib.

  • GZIPOutputStream / GZIPInputStream реализуют, как следует из названия, формат gzip.

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

Отказ от ответственности: Это состояние для Java SE, я полагаю, оно аналогично для Android, но я не могу этого гарантировать.

Найденная вами библиотека jzlib (я полагаю), которая является переопределением zlib на Java, также реализует все эти форматы данных (gzip был добавлен в последнем обновлении). Для интерактивного использования (на стороне сжатия) это предпочтительнее, поскольку позволяет выполнять некоторые действия по очистке, которые невозможны с классами java.util (кроме использования некоторого обходного пути, такого как изменение уровня сжатия), и это также может быть быстрее, поскольку позволяет избежать собственных вызовов (которые всегда имеют некоторые накладные расходы).

PS: Формат файла zip (или pkzip) также связан: он использует deflate внутренне для каждого файла внутри архива.

Комментарии:

1. Да, дубликаты Android java.util.zip точно так же, как в Java SE 6, так что все правильно.

2. Спасибо, это очень полезная информация. Как только вы упомянули контрольную сумму Adler-32, я точно знал, что это был метод, который использовал устаревший код, потому что я видел, как он создавал эту контрольную сумму в отладчике. Я подозреваю (или, по крайней мере, надеюсь), что мои данные действительно повреждены при переводе. Пока я проверил это только выборочно (проверил первые 100 байт или около того, последние 100 байт и больший фрагмент посередине) — но теперь я создам что-нибудь для сохранения обоих наборов данных в файл, чтобы я мог легко выполнить полное сравнение двоичных файлов.