Добавление заголовка в сжатый файл zlib - PullRequest
0 голосов
/ 04 октября 2018

Я пытаюсь использовать zlib для выкачивания (сжатия?) Данных из текстового файла.Кажется, это работает, когда я сжимаю файл, но я пытаюсь добавить сжатый файл zlib с пользовательским заголовком.И файл, и заголовок должны быть сжаты.Однако, когда я добавляю заголовок, длина сжатого (дефлированного) файла намного короче, чем ожидалось, и выглядит как недопустимый сжатый объект zlib.

Код прекрасно работает, пока я не добавлю блок заголовкакод между XXX комментариями ниже.

Переменная «FILE * source» является примером файла, я обычно использую / etc / passwd, а заголовок «char *» равен «blob 2172 \ 0».Без блока заголовка выход составляет 904 байта и является разборчивым (разжимаемым), но с заголовком получается только 30 байтов.Он также выглядит как недопустимый объект zlib с блоком заголовка кода.

Любые идеи, в которых я допускаю ошибку, в частности, почему вывод неверен и короче с заголовком?

Если это уместно, я пишу это во FreeBSD.

#define Z_CHUNK16384
#define HEX_DIGEST_LENGTH       257

int
zcompress_and_header(FILE *source, char *header)
{
int ret, flush;
z_stream strm;
unsigned int have;
unsigned char in[Z_CHUNK];
unsigned char out[Z_CHUNK];

FILE *dest = stdout; // This is a temporary test

strm.zalloc = Z_NULL;
strm.zfree = Z_NULL;
strm.opaque = Z_NULL;
ret = deflateInit(&strm, Z_BEST_SPEED);
//ret = deflateInit2(&strm, Z_BEST_SPEED, Z_DEFLATED, 15 | 16, 8,
Z_DEFAULT_STRATEGY);

if (ret != Z_OK)
     return ret;

/* XXX Beginning of writing the header */

strm.next_in = (unsigned char *) header;
strm.avail_in = strlen(header) + 1;

do {
     strm.avail_out = Z_CHUNK;
     strm.next_out = out;
     if (deflate (& strm, Z_FINISH) < 0) {
          fprintf(stderr, "returned a bad status of.\n");
          exit(0);
     }
     have = Z_CHUNK - strm.avail_out;
     fwrite(out, 1, have, stdout);
} while(strm.avail_out == 0);

/* XXX End of writing the header */

do {
     strm.avail_in = fread(in, 1, Z_CHUNK, source);
     if (ferror(source)) {
          (void)deflateEnd(&strm);
          return Z_ERRNO;
     }

     flush = feof(source) ? Z_FINISH : Z_NO_FLUSH;
     strm.next_in = in;

     do {
          strm.avail_out = Z_CHUNK;
          strm.next_out = out;
          ret = deflate(&strm, flush);
          have = Z_CHUNK - strm.avail_out;
          if (fwrite(out, 1, have, dest) != have || ferror(dest)) {
               (void)deflateEnd(&strm);
               return Z_ERRNO;
          }
     } while(strm.avail_out == 0);

} while (flush != Z_FINISH);

} // End of function

Ответы [ 2 ]

0 голосов
/ 05 октября 2018

Для ваших первых вызовов deflate() следует использовать Z_NO_FLUSH, а не Z_FINISH.Z_FINISH следует использовать только в том случае, если последним сжатым данным предоставляется вызов deflate().

0 голосов
/ 04 октября 2018

deflate не является архиватором.Это только сжимает поток.Как только поток исчерпан, ваши возможности очень ограничены.В руководстве четко сказано, что

Если для параметра flush задано значение Z_FINISH, ожидающий ввод обрабатывается, ожидающий вывод сбрасывается и возвращается с дефляцией с Z_STREAM_END, если свободного места было достаточно.Если deflate возвращается с Z_OK или Z_BUF_ERROR, эта функция должна быть вызвана снова с Z_FINISH и большим выходным пространством (обновлн.в_доступе), но без дополнительных входных данных, пока не будет возвращена с Z_STREAM_END или ошибкой.После того как deflate вернул Z_STREAM_END, единственными возможными операциями в потоке являются deflateReset или deflateEnd.

Однако вы вызываете deflate для файла после того, как вы Z_FINISHзаголовок, а zlib ведет себя непредсказуемо.Вероятное исправление заключается в том, чтобы вообще не использовать Z_FINISH для заголовка и позволить другой стороне понять, что первая строка в разархивированной строке является заголовком (или навязать некоторый протокол архивации, понятный обеим сторонам).

...