Is there a practical way to compress NSData?

后端 未结 7 1920
感情败类
感情败类 2020-12-14 11:40

I haven\'t seen any documentation on the topic, but that doesn\'t mean it doesn\'t exist.

7条回答
  •  爱一瞬间的悲伤
    2020-12-14 11:54

    Following @Zaph & @Brad Larson's posts, below are the 2 methods gzipInflate and gzipDeflate that work just fine to compress/decompress NSData. (code reformatted from cocoadev.com/wiki/NSDataCategory

    #import "zlib.h"
    // don't forget to add libz.1.2.x.dylib into your project
    
    - (NSData *)gzipInflate:(NSData*)data
    {
        if ([data length] == 0) return data;
    
        unsigned full_length = [data length];
        unsigned half_length = [data length] / 2;
    
        NSMutableData *decompressed = [NSMutableData dataWithLength: full_length + half_length];
        BOOL done = NO;
        int status;
    
        z_stream strm;
        strm.next_in = (Bytef *)[data bytes];
        strm.avail_in = [data 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:(NSData*)data
    {
        if ([data length] == 0) return data;
    
        z_stream strm;
    
        strm.zalloc = Z_NULL;
        strm.zfree = Z_NULL;
        strm.opaque = Z_NULL;
        strm.total_out = 0;
        strm.next_in=(Bytef *)[data bytes];
        strm.avail_in = [data 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];
    }
    

    From the log:

    [data length] (orig):989631
    [data length] (gz):  102757
    [data length] (ungz):989631
    

提交回复
热议问题