转载自:http://blog.csdn.net/huangmindong/article/details/24709351
/*
压缩和解压缩函数
数据压缩参考:
http://www.clintharris.net/2009/how-to-gzip-data-in-memory-using-objective-c/
数据解压缩参考:
ASIHttpRequest库的文件:ASIDataDecompressor.m
*/
添加 libbz2.1.0.dylib
头文件 .h文件
#import <Foundation/Foundation.h> #import "zlib.h" @interface LFCGzipUtility : NSObject { } +(NSData*) gzipData:(NSData*)pUncompressedData; //压缩 +(NSData*) ungzipData:(NSData *)compressedData; //解压缩 @end
.m文件
#import "LFCGzipUtility.h" @implementation LFCGzipUtility +(NSData*) gzipData: (NSData*)pUncompressedData { if (!pUncompressedData || [pUncompressedData length] == 0) { NSLog(@"%s: Error: Can't compress an empty or null NSData object.", __func__); return nil; } z_stream zlibStreamStruct; zlibStreamStruct.zalloc = Z_NULL; // Set zalloc, zfree, and opaque to Z_NULL so zlibStreamStruct.zfree = Z_NULL; // that when we call deflateInit2 they will be zlibStreamStruct.opaque = Z_NULL; // updated to use default allocation functions. zlibStreamStruct.total_out = 0; // Total number of output bytes produced so far zlibStreamStruct.next_in = (Bytef*)[pUncompressedData bytes]; // Pointer to input bytes zlibStreamStruct.avail_in = [pUncompressedData length]; // Number of input bytes left to process int initError = deflateInit2(&zlibStreamStruct, Z_DEFAULT_COMPRESSION, Z_DEFLATED, (15+16), 8, Z_DEFAULT_STRATEGY); if (initError != Z_OK) { NSString *errorMsg = nil; switch (initError) { case Z_STREAM_ERROR: errorMsg = @"Invalid parameter passed in to function."; break; case Z_MEM_ERROR: errorMsg = @"Insufficient memory."; break; case Z_VERSION_ERROR: errorMsg = @"The version of zlib.h and the version of the library linked do not match."; break; default: errorMsg = @"Unknown error code."; break; } NSLog(@"%s: deflateInit2() Error: \"%@\" Message: \"%s\"", __func__, errorMsg, zlibStreamStruct.msg); [errorMsg release]; return nil; } // Create output memory buffer for compressed data. The zlib documentation states that // destination buffer size must be at least 0.1% larger than avail_in plus 12 bytes. NSMutableData *compressedData = [NSMutableData dataWithLength:[pUncompressedData length] * 1.01 + 12]; int deflateStatus; do { // Store location where next byte should be put in next_out zlibStreamStruct.next_out = [compressedData mutableBytes] + zlibStreamStruct.total_out; // Calculate the amount of remaining free space in the output buffer // by subtracting the number of bytes that have been written so far // from the buffer's total capacity zlibStreamStruct.avail_out = [compressedData length] - zlibStreamStruct.total_out; deflateStatus = deflate(&zlibStreamStruct, Z_FINISH); } while ( deflateStatus == Z_OK ); // Check for zlib error and convert code to usable error message if appropriate if (deflateStatus != Z_STREAM_END) { NSString *errorMsg = nil; switch (deflateStatus) { case Z_ERRNO: errorMsg = @"Error occured while reading file."; break; case Z_STREAM_ERROR: errorMsg = @"The stream state was inconsistent (e.g., next_in or next_out was NULL)."; break; case Z_DATA_ERROR: errorMsg = @"The deflate data was invalid or incomplete."; break; case Z_MEM_ERROR: errorMsg = @"Memory could not be allocated for processing."; break; case Z_BUF_ERROR: errorMsg = @"Ran out of output buffer for writing compressed bytes."; break; case Z_VERSION_ERROR: errorMsg = @"The version of zlib.h and the version of the library linked do not match."; break; default: errorMsg = @"Unknown error code."; break; } NSLog(@"%s: zlib error while attempting compression: \"%@\" Message: \"%s\"", __func__, errorMsg, zlibStreamStruct.msg); [errorMsg release]; // Free data structures that were dynamically created for the stream. deflateEnd(&zlibStreamStruct); return nil; } // Free data structures that were dynamically created for the stream. deflateEnd(&zlibStreamStruct); [compressedData setLength: zlibStreamStruct.total_out]; NSLog(@"%s: Compressed file from %d KB to %d KB", __func__, [pUncompressedData length]/1024, [compressedData length]/1024); return compressedData; } +(NSData *)ungzipData:(NSData *)compressedData { if ([compressedData length] == 0) return compressedData; unsigned full_length = [compressedData length]; unsigned half_length = [compressedData length] / 2; NSMutableData *decompressed = [NSMutableData dataWithLength: full_length + half_length]; BOOL done = NO; int status; z_stream strm; strm.next_in = (Bytef *)[compressedData bytes]; strm.avail_in = [compressedData 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]; } return nil; } @end