我正在尝试使用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,有更好的第三种选择吗?
任何帮助将不胜感激。
答案 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;
}