测试对象如图:
#import "GZip.h"
#import <zlib.h>
@implementation GZip
+ (NSData *)gzipData:(NSData *)uncompressedData {
if ((uncompressedData == nil) ||
([uncompressedData length] == 0)) {
return uncompressedData;
}
z_stream strm;
strm.zalloc = Z_NULL;
strm.zfree = Z_NULL;
strm.opaque = Z_NULL;
strm.total_out = 0;
strm.next_in = (Bytef*)[uncompressedData bytes];
strm.avail_in = (unsigned int)[uncompressedData length];
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 = (Bytef*)[compressed mutableBytes] + strm.total_out;
strm.avail_out = (unsigned int)([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];
}
NSData *brs_gzipData(NSData *uncompressedData) {
if ((uncompressedData == nil) ||
([uncompressedData length] == 0)) {
return uncompressedData;
}
z_stream strm;
strm.zalloc = Z_NULL;
strm.zfree = Z_NULL;
strm.opaque = Z_NULL;
strm.total_out = 0;
strm.next_in = (Bytef*)[uncompressedData bytes];
strm.avail_in = (unsigned int)[uncompressedData length];
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 = (Bytef*)[compressed mutableBytes] + strm.total_out;
strm.avail_out = (unsigned int)([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];
}
NSData *brs_un_gzipData(NSData *gzipData){
if ([gzipData length] == 0) return gzipData;
unsigned full_length = (unsigned)[gzipData length];
unsigned half_length = (unsigned)[gzipData length] / 2;
NSMutableData *decompressed = [NSMutableData
dataWithLength:full_length + half_length];
BOOL done = NO;
int status;
z_stream strm;
strm.next_in = (Bytef *)[gzipData bytes];
strm.avail_in = (unsigned)[gzipData 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 = (uInt)([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 *)unGzipData:(NSData *)gzipData {
if ([gzipData length] == 0) return gzipData;
unsigned full_length = (unsigned)[gzipData length];
unsigned half_length = (unsigned)[gzipData length] / 2;
NSMutableData *decompressed = [NSMutableData
dataWithLength:full_length + half_length];
BOOL done = NO;
int status;
z_stream strm;
strm.next_in = (Bytef *)[gzipData bytes];
strm.avail_in = (unsigned)[gzipData 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 = (uInt)([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;
}
@end
测试代码:
NSData *data = [str dataUsingEncoding:(NSUTF8StringEncoding)];
CFAbsoluteTime startTime =CFAbsoluteTimeGetCurrent();
//在这写入要计算时间的代码
NSData *result = brs_gzipData(data);
CFAbsoluteTime linkTime = (CFAbsoluteTimeGetCurrent() - startTime);
NSLog(@"C函数压缩时间 %f ms", linkTime *1000.0);
CFAbsoluteTime startTime1 =CFAbsoluteTimeGetCurrent();
//在这写入要计算时间的代码
NSData *result1 = [GZip gzipData:data];
CFAbsoluteTime linkTime1 = (CFAbsoluteTimeGetCurrent() - startTime1);
NSLog(@"OC方法压缩时间 %f ms", linkTime1 *1000.0);
CFAbsoluteTime startTime2 =CFAbsoluteTimeGetCurrent();
//在这写入要计算时间的代码
NSData *result2 = [GZip unGzipData:result];
CFAbsoluteTime linkTime2 = (CFAbsoluteTimeGetCurrent() - startTime2);
NSLog(@"OC方法解压缩时间 %f ms", linkTime2 *1000.0);
CFAbsoluteTime startTime3 =CFAbsoluteTimeGetCurrent();
//在这写入要计算时间的代码
NSData *result3 = brs_un_gzipData(result1);
CFAbsoluteTime linkTime3 = (CFAbsoluteTimeGetCurrent() - startTime3);
NSLog(@"C方法解压缩时间 %f ms", linkTime3 *1000.0);
测试结果:
真机(iphonex)和模拟器的结果类似,但是真机的执行时间大概是模拟器的一半。
OC的文件压缩时间平均值总是少于C函数的压缩时间。
OC的文件解压缩时间平均值总是大于C函数的解压缩时间。
网友评论