1

我正在尝试使用来自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,我在这里读过,我知道它指的是 ASIHTTPReqest,但我认为可能正在使用 xcode 提供的相同 zlib 类进行解压缩,他们说这是缓冲区大小的错误不是能够处理由于空间而导致的文件解压缩。

我不完全确定这是否正确,他们提供了两种解决方案来修复,第一种是拆分数据包……这不是 imo 的选择,另一件事是增加缓冲区大小……我是想知道A,我怎么能这样做?B、有没有更好的第三种选择?

任何帮助将不胜感激。

4

1 回答 1

2

请参考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;
}
于 2012-12-13T21:09:55.813 回答