iOS开发常用

iOS 数据压缩与解压

2017-09-30  本文已影响29人  iOS_肖晨

不同数据类型与NSData互转参考如下:
NSData 类型转换

在开发中,经常要对比较大的数据进行压缩后再上传服务器,下面是我在项目中压缩数据时所使用的压缩三方库 (GZIP).
三方库使用了一个 NSData 的 Category, 方便data类型数据进行直接调用
地址: GZIP

.h

@interface NSData (GZIP)
- (nullable NSData *)gzippedDataWithCompressionLevel:(float)level;
- (nullable NSData *)gzippedData;
- (nullable NSData *)gunzippedData;
- (BOOL)isGzippedData;
@end

.m

#import "NSData+GZIP.h"
#import <zlib.h>
#pragma clang diagnostic ignored "-Wcast-qual"
@implementation NSData (GZIP)
- (NSData *)gzippedDataWithCompressionLevel:(float)level
{
    if (self.length == 0 || [self isGzippedData])
    {
        return self;
    }
    z_stream stream;
    stream.zalloc = Z_NULL;
    stream.zfree = Z_NULL;
    stream.opaque = Z_NULL;
    stream.avail_in = (uint)self.length;
    stream.next_in = (Bytef *)(void *)self.bytes;
    stream.total_out = 0;
    stream.avail_out = 0;
    static const NSUInteger ChunkSize = 16384;
    NSMutableData *output = nil;
    int compression = (level < 0.0f)? Z_DEFAULT_COMPRESSION: (int)(roundf(level * 9));
    if (deflateInit2(&stream, compression, Z_DEFLATED, 31, 8, Z_DEFAULT_STRATEGY) == Z_OK)
    {
        output = [NSMutableData dataWithLength:ChunkSize];
        while (stream.avail_out == 0)
        {
            if (stream.total_out >= output.length)
            {
                output.length += ChunkSize;
            }
            stream.next_out = (uint8_t *)output.mutableBytes + stream.total_out;
            stream.avail_out = (uInt)(output.length - stream.total_out);
            deflate(&stream, Z_FINISH);
        }
        deflateEnd(&stream);
        output.length = stream.total_out;
    }
    return output;
}
- (NSData *)gzippedData
{
    return [self gzippedDataWithCompressionLevel:-1.0f];
}
- (NSData *)gunzippedData
{
    if (self.length == 0 || ![self isGzippedData])
    {
        return self;
    }
    z_stream stream;
    stream.zalloc = Z_NULL;
    stream.zfree = Z_NULL;
    stream.avail_in = (uint)self.length;
    stream.next_in = (Bytef *)self.bytes;
    stream.total_out = 0;
    stream.avail_out = 0;
    NSMutableData *output = nil;
    if (inflateInit2(&stream, 47) == Z_OK)
    {
        int status = Z_OK;
        output = [NSMutableData dataWithCapacity:self.length * 2];
        while (status == Z_OK)
        {
            if (stream.total_out >= output.length)
            {
                output.length += self.length / 2;
            }
            stream.next_out = (uint8_t *)output.mutableBytes + stream.total_out;
            stream.avail_out = (uInt)(output.length - stream.total_out);
            status = inflate (&stream, Z_SYNC_FLUSH);
        }
        if (inflateEnd(&stream) == Z_OK)
        {
            if (status == Z_STREAM_END)
            {
                output.length = stream.total_out;
            }
        }
    }
    return output;
}
- (BOOL)isGzippedData
{
    const UInt8 *bytes = (const UInt8 *)self.bytes;
    return (self.length >= 2 && bytes[0] == 0x1f && bytes[1] == 0x8b);
}
@end
上一篇下一篇

猜你喜欢

热点阅读