Как использовать SetDictionary для deflate / inflate с необработанным deflate / inflate?

Я пытаюсь понять функциональность raw deflate, когда мы используем словарь. Я осведомлен о следующем. 1. Когда мы используем словарь, приложение должно предоставлять один и тот же словарь для deflate () и inflate (). 2. При выполнении raw deflate эта функция должна вызываться либо перед любым вызовом deflate, либо сразу после завершения блока deflate, то есть после того, как весь ввод был использован и весь вывод был доставлен при использовании любой из опций flush Z_BLOCK , Z_PARTIAL_FLUSH, Z_SYNC_FLUSH или Z_FULL_FLUSH. (Из документации zlib).

Но следующее приложение не может распаковать то, что было сжато ранее тем же приложением. Сжатие и распаковка прошли успешно, но есть несоответствие между входным и несжатым файлом.

спустить:

    do {
        ret = deflateSetDictionary(&strm, dictionary, sizeof(dictionary));
        if(ret != Z_OK) {
            fprintf(stderr, "Failed to set deflate dictionary\n");
            return Z_STREAM_ERROR;
        }
        strm.avail_in = fread(in, 1, CHUNK, source);
        if (ferror(source)) {
            (void)deflateEnd(&strm);
            return Z_ERRNO;
        }
        flush = feof(source) ? Z_FINISH : Z_FULL_FLUSH;
        strm.next_in = in;

        /* run deflate() on input until output buffer not full, finish
           compression if all of source has been read in */
        do {
            strm.avail_out = CHUNK;
            strm.next_out = out;
            ret = deflate(&strm, flush);    /* no bad return value */
            assert(ret != Z_STREAM_ERROR);  /* state not clobbered */
            have = CHUNK - strm.avail_out;
            if (fwrite(out, 1, have, dest) != have || ferror(dest)) {
                (void)deflateEnd(&strm);
                return Z_ERRNO;
            }
        } while (strm.avail_out == 0);
        assert(strm.avail_in == 0);     /* all input will be used */

        /* done when last data in file processed */
    } while (flush != Z_FINISH);
    assert(ret == Z_STREAM_END);     

надуть:

    do {
        ret = inflateSetDictionary(&strm, dictionary, sizeof(dictionary));
        if(ret != Z_OK) {
            fprintf(stderr, "Failed to set inflate dictionary\n");
            return Z_STREAM_ERROR;
        }
        strm.avail_in = fread(in, 1, CHUNK, source);
        if (ferror(source)) {
            (void)inflateEnd(&strm);
            return Z_ERRNO;
        }
        if (strm.avail_in == 0)
            break;
        strm.next_in = in;


        /* run inflate() on input until output buffer not full */
        do {
            strm.avail_out = CHUNK;
            strm.next_out = out;
            ret = inflate(&strm, Z_FULL_FLUSH);
            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;
            if (fwrite(out, 1, have, dest) != have || ferror(dest)) {
                (void)inflateEnd(&strm);
                return Z_ERRNO;
            }
        } while (strm.avail_out == 0);

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

person Chinna    schedule 08.06.2015    source источник


Ответы (1)


При дефляции вы устанавливаете один и тот же словарь каждые CHUNK входных байтов. Почему? Вы должны использовать deflateSetDictionary() один раз, сразу после deflateInit2(). С этого момента сами входные данные должны служить лучшим источником сопоставления строк, чем словарь, который вы могли бы предоставить.

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

person Mark Adler    schedule 12.06.2015
comment
Спасибо за Ваш ответ. Я вызываю deflateSetdictionary () для каждого входного байта CHUNK только в экспериментальных целях. В любом случае я получил разъяснения по своему вопросу во второй половине вашего ответа. - person Chinna; 12.06.2015