iOSアプリ開発でデータをgzip圧縮する方法

iOSアプリで端末からサーバに対して大きなデータを通信する際に、通信データをgzipに圧縮して通信を行うことがある。
今回は、iOSアプリでデータをgzip圧縮する方法を紹介する。

具体的には、NSData型のデータを引数として受け取り、gzip圧縮したデータをNSData型で返却する方法を紹介する。


GzipUtil.h

#import <Foundation/Foundation.h>

@interface GzipUtil : NSObject

+ (NSData *)execGzip:(NSData *)sourceData;

@end

GzipUtil.m

#import "GzipUtil.h"

#import <zlib.h>

@implementation GzipUtil

static const NSUInteger ChunkSize = 16384;
static const float level = -1.0f;

+ (NSData *)execGzip:(NSData *)sourceData
{
    if ([sourceData length])
    {
        z_stream stream;
        stream.zalloc = Z_NULL;
        stream.zfree = Z_NULL;
        stream.opaque = Z_NULL;
        stream.avail_in = (uint)[sourceData length];
        stream.next_in = (Bytef *)[sourceData bytes];
        stream.total_out = 0;
        stream.avail_out = 0;
        
        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)
        {
            NSMutableData *data = [NSMutableData dataWithLength:ChunkSize];
            while (stream.avail_out == 0)
            {
                if (stream.total_out >= [data length])
                {
                    data.length += ChunkSize;
                }
                stream.next_out = (uint8_t *)[data mutableBytes] + stream.total_out;
                stream.avail_out = (uInt)([data length] - stream.total_out);
                deflate(&stream, Z_FINISH);
            }
            deflateEnd(&stream);
            data.length = stream.total_out;
            return data;
        }
    }
    return nil;
}

@end

<使い方>

//使用するクラスで「GzipUtil.h」をインポートしておく

//圧縮対象の文字列
NSString *buf = @"abcdefghijabcdefghijabcdefghijabcdefghij";
NSLog(@"NSString:%@", buf);

//NSData型に変換    
NSData *dataBuf = [buf dataUsingEncoding:NSUTF8StringEncoding];
NSLog(@"NSData:%@", dataBuf);

//gzip圧縮実行
NSData *gzipBuf = [GzipUtil execGzip:dataBuf];
NSLog(@"gzip圧縮後NSData:%@", gzipBuf);

<実行結果>

2014-11-04 19:01:37.847 GzipSample[1242:564671] NSString:abcdefghijabcdefghijabcdefghijabcdefghij
2014-11-04 19:01:37.848 GzipSample[1242:564671] NSData:<61626364 65666768 696a6162 63646566 6768696a 61626364 65666768 696a6162 63646566 6768696a>
2014-11-04 19:01:37.848 GzipSample[1242:564671] gzip圧縮後NSData:<1f8b0800 00000000 00034b4c 4a4e494d 4bcfc8cc 4ac4cb02 00e031c7 ba280000 00>

GzipUtilに記載したソースコードに関しては、筆者も詳細は理解していない。
GZIPというライブラリのソースコードを参考(ほぼそのまま)に記述した。

<お勧め書籍>

詳解 Objective-C 2.0 第3版
iOSアプリ開発技術者として仕事をするのであれば、必ず読んでおくべき書籍である。
筆者も何度も繰り返し精読している。