首页 > 解决方案 > 使用 C 的 Zlib 和 Gzip:不正确的标头检查 (Z_DATA_ERROR)

问题描述

我正在从此处下载 .txt.gz 格式的图形数据集。下载后我尝试使用 zlib 解压缩它。我使用的代码大部分是从zpipe.c示例中抄袭的,对使用gzopengzfreadgzcloseZ_SYNC_FLUSH加号进行了更改inflateInit2(&stream, (32 + MAX_WBITS))。我也试过(16 + MAX_WBITS)。

如标题中所述,我收到的错误消息是Z_DATA_ERROR (-3)“不正确的标头检查”。

现在可以使用 zcat(和 zless)打开数据,并且标题似乎也可以:

1F 8B            gzip  
08               deflate  
00               no special information
33 0c 36 59      last modification
00               no extra flags
03               unix

gz 文件的前 32 个字节

简而言之,我不知道有什么问题。

下面是我使用的代码。

int uncompress_dataset(const char* gz_path, const char* out_path) {
    int ret;
    unsigned have;
    z_stream stream;
    FILE* out_file;
    gzFile in_gz_file;
    unsigned char in[CHUNK];
    unsigned char out[CHUNK];
    int err_no = 0;
    const char* emsg;

    stream.zalloc = Z_NULL;
    stream.zfree = Z_NULL;
    stream.opaque = Z_NULL;
    stream.avail_in = 0;
    stream.next_in = Z_NULL;
    ret = inflateInit2(&stream, (32 + MAX_WBITS));
    if (ret != Z_OK) {
        zlib_error(ret);
        return -1;
    }

    out_file = fopen(out_path, "wb");
    in_gz_file = gzopen(gz_path, "rb");

    if (out_file == NULL) {
        printf("%s", "couldn't open the output file");
        inflateEnd(&stream);
        return -1;
    }
    if (in_gz_file == NULL) {
        printf("%s", "couldn't open the input file as gzip");
        fclose(out_file);
        inflateEnd(&stream);
        return -1;
    }

    do {
        stream.avail_in  = gzfread(in, 1, CHUNK, in_gz_file);
        if (stream.avail_in == 0) {
            emsg = gzerror(in_gz_file, &err_no);
            if (err_no < 0 || err_no == 2) {
                printf("Error when reading %s", emsg);
                zlib_error(err_no);
                inflateEnd(&stream);
                fclose(out_file);
                gzclose(in_gz_file);
                return -1;
            } else {
                break;
            }
        }

        stream.next_in = in;
        do {
            stream.avail_out = CHUNK;
            stream.next_out = out;

            ret = inflate(&stream, Z_SYNC_FLUSH);
            printf("Return value of inflate: %i\n", ret);
            assert(ret != Z_STREAM_ERROR);
            switch (ret) {
                case Z_NEED_DICT:
                    ret = Z_DATA_ERROR;
                case Z_DATA_ERROR:
                case Z_MEM_ERROR:
                    printf("Error: %s\n", stream.msg);
                    inflateEnd(&stream);
                    zlib_error(ret);
                    fclose(out_file);
                    gzclose(in_gz_file);
                    return -1;
            }

            have = CHUNK - stream.avail_out;
            if (fwrite(out, 1, have, out_file) != have || ferror(out_file)) {
                inflateEnd(&stream);
                zlib_error(ret);
                fclose(out_file);
                gzclose(in_gz_file);
                return -1;
            }
        } while (stream.avail_out == 0);
    } while (ret != Z_STREAM_END);

    fclose(out_file);
    gzclose(in_gz_file);
    inflateEnd(&stream);
    return ret == Z_STREAM_END ? Z_OK : Z_DATA_ERROR;
}

标签: cgzipzlib

解决方案


推荐阅读