Gzip compression/decompression

来源:互联网 发布:运营的数据分析 编辑:程序博客网 时间:2024/06/05 07:49

http://deusty.blogspot.com/2007/07/gzip-compressiondecompression.html


A long time ago I grabbed some code from CocoaDev to allow zlib compression/decompression of NSData. But a couple months ago I went looking for similar code to allow gzip compression/decompression. At the time I didn't find any, and found myself wading through the zlib documentation and header files until I came up with a solution. I've recently noticed that someone else on CocoaDev has also mentioned the solution, but it looks like they didn't fully implement a deflate version of it. So, without further ado, here is an NSData category that adds support for gzip compression and decompression:


@interface NSData (DDData)// gzip compression utilities- (NSData *)gzipInflate;- (NSData *)gzipDeflate;@end

-----------------------------------------

#include
@implementation NSData (DDData)- (NSData *)gzipInflate{ if ([self length] == 0) return self;  unsigned full_length = [self length]; unsigned half_length = [self length] / 2;  NSMutableData *decompressed = [NSMutableData dataWithLength: full_length + half_length]; BOOL done = NO; int status;  z_stream strm; strm.next_in = (Bytef *)[self bytes]; strm.avail_in = [self length]; strm.total_out = 0; strm.zalloc = Z_NULL; strm.zfree = Z_NULL;  if (inflateInit2(&strm, (15+32)) != Z_OK) return nil; while (!done) {  // Make sure we have enough room and reset the lengths.  if (strm.total_out >= [decompressed length])   [decompressed increaseLengthBy: half_length];  strm.next_out = [decompressed mutableBytes] + strm.total_out;  strm.avail_out = [decompressed length] - strm.total_out;    // Inflate another chunk.  status = inflate (&strm, Z_SYNC_FLUSH);  if (status == Z_STREAM_END) done = YES;  else if (status != Z_OK) break; } if (inflateEnd (&strm) != Z_OK) return nil;  // Set real length. if (done) {  [decompressed setLength: strm.total_out];  return [NSData dataWithData: decompressed]; } else return nil;}- (NSData *)gzipDeflate{ if ([self length] == 0) return self;  z_stream strm;  strm.zalloc = Z_NULL; strm.zfree = Z_NULL; strm.opaque = Z_NULL; strm.total_out = 0; strm.next_in=(Bytef *)[self bytes]; strm.avail_in = [self length];  // Compresssion Levels: //   Z_NO_COMPRESSION //   Z_BEST_SPEED //   Z_BEST_COMPRESSION //   Z_DEFAULT_COMPRESSION  if (deflateInit2(&strm, Z_DEFAULT_COMPRESSION, Z_DEFLATED, (15+16), 8, Z_DEFAULT_STRATEGY) != Z_OK) return nil;  NSMutableData *compressed = [NSMutableData dataWithLength:16384];  // 16K chunks for expansion  do {    if (strm.total_out >= [compressed length])   [compressed increaseLengthBy: 16384];    strm.next_out = [compressed mutableBytes] + strm.total_out;  strm.avail_out = [compressed length] - strm.total_out;    deflate(&strm, Z_FINISH);     } while (strm.avail_out == 0);  deflateEnd(&strm);  [compressed setLength: strm.total_out]; return [NSData dataWithData:compressed];}@end

原创粉丝点击