C ++ Inflate массив символов gzip

Я пытаюсь использовать zlib для распаковки (раздувания) некоторых полезных данных IP-пакетов, которые сжимаются с помощью gzip. Тем не менее, у меня есть некоторые трудно понять некоторые документы, предоставляемые zlib, которые охватывают инфляцию. У меня есть массив символов, который заполняет моя программа, но я не могу надуть его следующим кодом:

const u_char payload; /*contains gzip data,
captured prior to this point in the program*/

/*read compressed contents*/
int ret; //return val
z_stream stream;
unsigned char out[MEM_CHUNK]; //output array, MEM_CHUNK defined as 65535

/* allocate inflate state */
stream.zalloc = Z_NULL;
stream.zfree = Z_NULL;
stream.opaque = Z_NULL;
stream.avail_in = size_payload; // size of input
stream.next_in = (Bytef *)payload; // input char array
stream.avail_out = (uInt)sizeof(out); // size of output
stream.next_out = (Bytef *)out; // output char array

ret = inflateInit(&stream);
inflate(&stream, Z_NO_FLUSH);
inflateEnd(&stream);

printf("Inflate: %s\n\n", out);

в документация zlib, они постоянно раздуваются с помощью цикла do / while, проверяя наличие флага Z_STREAM_END. Я немного запутался здесь, потому что кажется, что они работают из файла, а я нет. Нужен ли мне этот цикл, или я могу предоставить массив символов без зацикливания на inflate?

Любое руководство здесь будет по достоинству оценено. Я довольно новичок в работе со сжатием и C ++.

Благодарю.

0

Решение

Предполагая, что вы даете inflate соответствующий и полный «сжатый поток», и достаточно места для вывода данных, вам нужно всего лишь вызвать inflate один раз.

Изменить: это не написано так четко, как в документация zlib, но он говорит:

inflate распаковывает как можно больше данных и останавливается, когда
входной буфер становится пустым или выходной буфер заполнен. Это может
ввести некоторую задержку вывода (чтение ввода без производства каких-либо
вывод) кроме случаев, когда принудительно смывает.

Конечно, для любого потока, который еще не «находится в памяти и завершен», вы хотите запускать его блок за блоком, так как он будет иметь меньшее общее время выполнения (вы можете распаковать его во время получения данных [из сети или файловой системы). предварительное получение кэширования] для следующего блока).

Вот вся функция из вашего примера кода. Я удалил текстовые компоненты со страницы, чтобы сконцентрировать код, и пометил разделы буквами // A , // B и т. д., затем отметили, пытались объяснить разделы ниже.

int inf(FILE *source, FILE *dest)
{
int ret;
unsigned have;
z_stream strm;
unsigned char in[CHUNK];     // A
unsigned char out[CHUNK];

/* allocate inflate state */
strm.zalloc = Z_NULL;        // B
strm.zfree = Z_NULL;
strm.opaque = Z_NULL;
strm.avail_in = 0;
strm.next_in = Z_NULL;
ret = inflateInit(&strm);    // C
if (ret != Z_OK)
return ret;

/* decompress until deflate stream ends or end of file */
do {
strm.avail_in = fread(in, 1, CHUNK, source);     // D
if (ferror(source)) {
(void)inflateEnd(&strm);      // E
return Z_ERRNO;
}
if (strm.avail_in == 0)           // F
break;
strm.next_in = in;                // G/* run inflate() on input until output buffer not full */
do {
strm.avail_out = CHUNK;       // H
strm.next_out = out;

ret = inflate(&strm, Z_NO_FLUSH);  // I
assert(ret != Z_STREAM_ERROR);  /* state not clobbered */
switch (ret) {
case Z_NEED_DICT:
ret = Z_DATA_ERROR;     /* and fall through */
case Z_DATA_ERROR:
case Z_MEM_ERROR:
(void)inflateEnd(&strm);
return ret;
}

have = CHUNK - strm.avail_out;     // J
if (fwrite(out, 1, have, dest) != have || ferror(dest)) {
(void)inflateEnd(&strm);
return Z_ERRNO;
}

} while (strm.avail_out == 0);         // K

/* done when inflate() says it's done */
} while (ret != Z_STREAM_END);             // L

/* clean up and return */
(void)inflateEnd(&strm);
return ret == Z_STREAM_END ? Z_OK : Z_DATA_ERROR;
}

: in является входным буфером (мы читаем из файла в этот буфер, а затем передаем его inflate Некоторое время спустя out это выходной буфер, который используется inflate хранить выходные данные.

В: Настроить z_stream объект называется strm, Это содержит различные поля, большинство из которых здесь не важны (таким образом, установлено значение Z_NULL). Важными из них являются avail_in а также next_in так же как avail_out а также next_out (которые устанавливаются позже).

С: Начать процесс инфляции. Это устанавливает некоторые внутренние структуры данных и просто делает inflate сама функция «готова к запуску».

DСчитать объем данных из файла. Сохранить количество прочитанных байтов в strm.avail_inи фактические данные входят в in,

Е: Если мы ошиблись, закончите inflate позвонив inflateEnd, Работа выполнена.

F: Нет данных, мы закончили.

г: Установить, откуда поступают наши данные (next_in установлен на входной буфер, in).

ЧАС: Мы сейчас находимся в цикле, чтобы раздуть вещи. Здесь мы устанавливаем выходной буфер: next_out а также avail_out указать, куда выводится и сколько места там, соответственно.

я: Вызов inflate сам. Это распакует часть входного буфера, пока вывод не будет заполнен.

J: Подсчитать, сколько данных доступно на этом шаге (have количество байтов).

К: Пока у нас не осталось места, когда inflate готово — это означает, что вывод завершен для данных в in буфер, а не из свободного места в буфере выхода. Пришло время прочитать еще данные из входного файла.

L: Если код ошибки от inflate Звонок «счастлив», иди снова.

Теперь, очевидно, если вы читаете из сети и распаковываете в память, вам нужно заменить fread а также fwrite с некоторыми подходящими read from network а также memcpy вместо этого введите звонки. Я не могу точно сказать вам, что это такое, так как вы не предоставили ничего, чтобы объяснить, откуда ваши данные — вы звоните recv или же read или же WSARecv, или что-то другое? — и куда это идет?

4

Другие решения

Других решений пока нет …