Как определить сжатый размер из zlib для сжатых данных? - PullRequest
4 голосов
/ 20 января 2010

Я использую zlib для сжатия gzip. zlib записывает данные непосредственно в открытый TCP-сокет после сжатия.

/* socket_fd is a file descriptor for an open TCP socket */
gzFile gzf = gzdopen(socket_fd, "wb");
int uncompressed_bytes_consumed = gzwrite(gzf, buffer, 1024);

(конечно, вся обработка ошибок удалена)

Вопрос в том, как определить, сколько байтов было записано в сокет? Все функции gz * в zlib работают с подсчетом / смещением байтов в несжатом домене и говорят, что поиск не работает для сокетов.

Заголовок zlib.h гласит: «Эта библиотека может также опционально читать и записывать потоки gzip в память». Запись в буфер будет работать (тогда я смогу впоследствии записать буфер в сокет), но я не вижу, как это сделать с интерфейсом.

Ответы [ 2 ]

0 голосов
/ 23 января 2010

zlib фактически может записывать данные в формате gzip в буфер в памяти.

Эта запись zlib faq относится к комментариям в zlib.h. В заголовочном файле в комментарии для deflateInit2 () упоминается, что вы должны (произвольно?) Добавить 16 к 4-му параметру (windowBits), чтобы библиотека форматировала поток deflate в формате gzip (вместо значения по умолчанию "zlib "формат).

Этот код правильно устанавливает состояние zlib для кодирования gzip в буфер:

#include <zlib.h>
z_stream stream;
stream.zalloc = Z_NULL;
stream.zfree = Z_NULL;
stream.opaque = Z_NULL;
int level = Z_DEFAULT_COMPRESSION;
int method = Z_DEFLATED;  /* mandatory */
int windowBits = 15 + 16; /* 15 is default as if deflateInit */
                          /* were used, add 16 to enable gzip format */
int memLevel = 8;         /* default */
int strategy = Z_DEFAULT_STRATEGY;
if(deflateInit2(&stream, level, method, windowBits, memLevel, strategy) != Z_OK)
{
    fprintf(stderr, "deflateInit failed\n");
    exit(EXIT_FAILURE);
}

/* now use the deflate function as usual to gzip compress */
/* from one buffer to another. */

Я подтвердил, что эта процедура выдает тот же двоичный вывод, что и интерфейс gzopen / gzwrite / gzclose.

0 голосов
/ 20 января 2010

Вы сможете сделать это с помощью серии вызовов deflate*. Я не собираюсь показывать вам все, но этот пример программы (которую я назвал «test.c» в моем каталоге) должен помочь вам начать:

#include <zlib.h>
#include <stdlib.h>
#include <stdio.h>

char InputBufferA[4096];
char OutputBufferA[4096];

int main(int argc, char *argv[])
{
    z_stream Stream;
    int InputSize;
    FILE *FileP;

    Stream.zalloc = malloc;
    Stream.zfree = free;
    /* initialize compression */
    deflateInit(&Stream, 3);
    FileP = fopen("test.c", "rb");
    InputSize = fread((void *) InputBufferA, 1, sizeof(InputBufferA), FileP);
    fclose(FileP);
    Stream.next_in = InputBufferA;
    Stream.avail_in = InputSize;
    Stream.next_out = OutputBufferA;
    Stream.avail_out = sizeof(OutputBufferA);
    deflate(&Stream, Z_SYNC_FLUSH);
    /* OutputBufferA is now filled in with the compressed data. */
    printf("%d bytes input compressed to %d bytes\n", Stream.total_in, Stream.total_out);
    exit(0);
}

Обратитесь к документации deflate от zlib.h.

...