【问题标题】:ZLib Inflate() failing with -3 Z_DATA_ERRORZLib Inflate() 以 -3 Z_DATA_ERROR 失败
【发布时间】:2013-09-09 14:32:32
【问题描述】:

我正在尝试通过调用 inflate 函数来解压缩文件,但即使我使用网站上的示例程序,它也总是会出现 Z_DATA_ERROR 失败。我在想可能不支持我拥有的 zip 文件。我在下面附上了一张 zip 头的图片。

这是我为执行解压缩而编写的函数。我一次读入整个文件(大约 34KB)并将其传递给这个函数。请注意,我尝试使用 zip 标头传递整个 zip 文件以及跳过 zip 文件标头,并且仅在调用 inflate() 时传递压缩数据都失败并出现 Z_DATA_ERROR。

int CHttpDownloader::unzip(unsigned char * pDest, unsigned long * ulDestLen, unsigned char *  pSource, int iSourceLen){
    int ret = 0;
    unsigned int uiUncompressedBytes = 0; // Number of uncompressed bytes returned from inflate() function
    unsigned char * pPositionDestBuffer = pDest; // Current position in dest buffer
    unsigned char * pLastSource = &pSource[iSourceLen]; // Last position in source buffer
    z_stream strm;

    // Skip over local file header
    SLocalFileHeader * header = (SLocalFileHeader *) pSource;
    pSource += sizeof(SLocalFileHeader) + header->sFileNameLen + header->sExtraFieldLen;


    // We should now be at the beginning of the stream data
    /* allocate inflate state */
    strm.zalloc = Z_NULL;
    strm.zfree = Z_NULL;
    strm.opaque = Z_NULL;
    strm.avail_in = 0;
    strm.next_in = Z_NULL;
    ret = inflateInit2(&strm, 16+MAX_WBITS);
    if (ret != Z_OK){
        return -1;
    }

    // Uncompress the data
    strm.avail_in = header->iCompressedSize; //iSourceLen;
    strm.next_in = pSource;

    do {
        strm.avail_out = *ulDestLen;
        strm.next_out = pPositionDestBuffer;
        ret = inflate(&strm, Z_NO_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 -2;
        }
        uiUncompressedBytes = *ulDestLen - strm.avail_out;
        *ulDestLen -= uiUncompressedBytes; // ulDestSize holds number of free/empty bytes in buffer
        pPositionDestBuffer += uiUncompressedBytes;
    } while (strm.avail_out == 0);

    // Close the decompression stream
    inflateEnd(&strm);
    ASSERT(ret == Z_STREAM_END);

    return 0;
}

所以我的问题是,ZLib 的 inflate() 函数不支持我正在读取的 zip 文件类型吗?还是我的 CHttpDownloader::unzip() 函数有问题?感谢您的帮助:)

【问题讨论】:

  • 您是否尝试过将此代码与您创建的另一个简单 zip 文件一起使用?
  • 我只是用 WinZip 创建的一个简单的 zip 文件尝试了它,它失败并出现同样的错误。
  • 见马克阿德勒的回答。他在这个话题上绝对是正确的;) Zlib 不是 ZIP。 ZIP 是建立在 zlib 压缩算法之上的存档文件格式。

标签: c++ zlib unzip


【解决方案1】:

Inflate() 失败,因为它正在寻找不存在的 GZip 标头。如果您使用以下命令初始化流:

ret = inflateInit2(&strm, -MAX_WBITS);

传递负的窗口位值可防止 inflate 检查 gzip 或 zlib 标头,并且解压缩按预期工作。

【讨论】:

  • 如果你首先处理zip头信息,那么你就是这样解压的,这样你就可以找到deflate流。
  • 感谢您的帮助。我没有使用 Minizip,因为我解压缩的文件在内存中,没有写入磁盘。跳过本地文件头并使用负窗口位调用 inflateinit2 解决了这个问题。之前我不太了解 zip 文件和 deflate 流之间的区别,但现在它更有意义了。再次感谢:)
  • 哇,这有多疯狂?文档实际上根本没有提供任何线索。应该是 zlib 的常见问题 IMO 的一部分
  • 太疯狂了。
【解决方案2】:

50 4B 03 04 开头的文件是一个 zip 文件。 zlib 库不直接处理 zip 文件。 zlib 可以帮助进行压缩、解压缩和 crc 计算。但是,您需要其他代码来处理 zip 文件格式。

你可以看看contrib/minizip in the zlib distribution,或者libzip

【讨论】:

  • 看起来将 ZIP/zlib 混合在一起就像混合 FTP 和 SFTP )
  • 她已经考虑到这一点,并试图解压缩 zip 存档中的原始数据
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-11-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多