尝试解压缩zlib数据时Z_BUF_ERROR -5

时间:2012-12-13 20:45:32

标签: objective-c ios zlib

我正在尝试使用ObjectiveZlib示例代码中的dataByDecompressingData:方法解压缩一些zlib数据,我有一些帮助转换为与Objective-c而不是c ++一起使用。代码

- (NSData*) dataByDecompressingData:(NSData*)data{
    Byte* bytes = (Byte*)[data bytes];
    NSInteger len = [data length];
    NSMutableData *decompressedData = [[NSMutableData alloc] initWithCapacity:COMPRESSION_BLOCK];
    Byte* decompressedBytes = (Byte*) malloc(COMPRESSION_BLOCK);

    z_stream stream;
    int err;
    stream.zalloc = (alloc_func)0;
    stream.zfree = (free_func)0;
    stream.opaque = (voidpf)0;

    stream.next_in = bytes;
    err = inflateInit(&stream);
    CHECK_ERR(err, @"inflateInit");

    while (true) {
        stream.avail_in = len - stream.total_in;
        stream.next_out = decompressedBytes;
        stream.avail_out = COMPRESSION_BLOCK;
        err = inflate(&stream, Z_NO_FLUSH);
        [decompressedData appendBytes:decompressedBytes length:(stream.total_out-[decompressedData length])];
        if(err == Z_STREAM_END)
            break;
        CHECK_ERR(err, @"inflate");
    }

    err = inflateEnd(&stream);
    CHECK_ERR(err, @"inflateEnd");

    free(decompressedBytes);
    return decompressedData;
}

一旦运行我然后得到Z_BUF_ERROR,我读过here我知道它是指ASIHTTPReqest,但我想可能正在使用xcode提供的相同zlib类来解压缩,并且他们说它出错了由于空间原因,缓冲区的大小无法处理文件的解压缩。

我不完全确定如果这是正确的,他们提供了两个解决方案来解决,第一个是分割数据包...这不是一个选项imo,另一个要做的是增加缓冲区大小。我想知道A,我怎么能这样做? B,有更好的第三种选择吗?

任何帮助将不胜感激。

1 个答案:

答案 0 :(得分:1)

请参阅http://www.zlib.net/zlib_how.html

  

Z_BUF_ERROR将在下面进一步解释,但足以说明这只是一个指示inflate()不会消耗更多输入或产生更多输出。可以使用更多输出空间或更多可用输入再次调用inflate(),它将在此代码中。

我看到的一些错误:

1 /每次设置stream.next_in时,您也应设置stream.avail_in。请注意,当您未提供下一个输入块时,不应更改stream.avail_in。在致电avail_in之前设置初始inflateInit可能是一个好主意。

2 /使用inflateInit2(&stream, -MAX_WBITS)可能是一个好主意。请注意,inflateInit的正常版本不检查压缩类型(gzip或zlib)的数据,如果选择gzip,则解压缩将失败。

(应该工作,没有经过测试而写)

-(NSData*)decompressData:(NSData*)compressedData {
    z_stream stream;

    stream.zalloc = Z_NULL;
    stream.zfree = Z_NULL;
    stream.opaque = Z_NULL;

    //we set the input, no need to change the values later
    stream.next_in = (Bytef *) [compressedData bytes];
    stream.avail_in = compressedData.length;  

    int result = inflateInit2(&stream, -MAX_WBITS);

    if (result != Z_OK) {
        return nil;
    }

    NSMutableData* uncompressedData = [NSMutableData data];
    //make buffer big enough - 128KB
    int bufferLength = 128 * 1024;
    char *buffer = malloc(bufferLength);

    while (true) {
        stream.next_out = buffer;
        stream.avail_out = bufferLength;

        //calling with Z_FINISH because we already have all the input
        result = inflate(&stream, Z_FINISH);

        if (result != Z_OK && result != Z_STREAM_END) {
             inflateEnd(&stream);
             free(buffer);
             return nil;
        }

        [uncompressedData appendBytes:buffer length:(bufferLength - stream.avail_out)];

        if (result == Z_STREAM_END) {
            break;
        }
    }


    inflateEnd(&stream);
    free(buffer);

    return uncompressedData;
}