iPhone 上的压缩 API

发布于 2024-07-08 12:02:59 字数 246 浏览 6 评论 0原文

是否有可在 iPhone 上使用的压缩 API? 我们正在为我们的 iPhone 应用程序构建一些 RESTful Web 服务来进行对话,但我们希望至少压缩一些对话以提高效率。

我不在乎格式(ZIP、LHA,等等)是什么,也不需要是安全的。

一些受访者指出,服务器可以压缩其输出,iPhone 可以使用它。 我们的情况恰恰相反。 我们将把压缩内容发布到网络服务。 我们不关心相反的压缩。

Is there a compression API available for use on the iPhone? We're building some RESTful web services for our iPhone app to talk to, but we want to compress at least some of the conversations for efficiency.

I don't care what the format (ZIP, LHA, whatever) is, and it does not need to be secure.

Some respondents have pointed out that the server can compress its output, and the iPhone can consume that. The scenario we have is exactly the reverse. We'll be POSTing compressed content to the web service. We're not concerned with compression going the other way.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(8

紧拥背影 2024-07-15 12:02:59

如果您将对话数据存储在 NSData 对象中,CocoaDev wiki 上的人员已经发布了 NSData类别,添加 gzip 和 zlib 压缩/解压缩作为简单方法。 这些在我的 iPhone 应用程序。

由于上面的链接已经失效,而 CocoaDev wiki 正在转移到新的主机,所以我在下面完整地复制了这个类别。

接口:

@interface NSData (NSDataExtension)

// Returns range [start, null byte), or (NSNotFound, 0).
- (NSRange) rangeOfNullTerminatedBytesFrom:(int)start;

// Canonical Base32 encoding/decoding.
+ (NSData *) dataWithBase32String:(NSString *)base32;
- (NSString *) base32String;

// COBS is an encoding that eliminates 0x00.
- (NSData *) encodeCOBS;
- (NSData *) decodeCOBS;

// ZLIB
- (NSData *) zlibInflate;
- (NSData *) zlibDeflate;

// GZIP
- (NSData *) gzipInflate;
- (NSData *) gzipDeflate;

//CRC32
- (unsigned int)crc32;

// Hash
- (NSData*) md5Digest;
- (NSString*) md5DigestString;
- (NSData*) sha1Digest;
- (NSString*) sha1DigestString;
- (NSData*) ripemd160Digest;
- (NSString*) ripemd160DigestString;

@end

实现:

#import "NSData+CocoaDevUsersAdditions.h"
#include <zlib.h>
#include <openssl/md5.h>
#include <openssl/sha.h>
#include <openssl/ripemd.h>


@implementation NSData (NSDataExtension)

// Returns range [start, null byte), or (NSNotFound, 0).
- (NSRange) rangeOfNullTerminatedBytesFrom:(int)start
{
    const Byte *pdata = [self bytes];
    int len = [self length];
    if (start < len)
    {
        const Byte *end = memchr (pdata + start, 0x00, len - start);
        if (end != NULL) return NSMakeRange (start, end - (pdata + start));
    }
    return NSMakeRange (NSNotFound, 0);
}

+ (NSData *) dataWithBase32String:(NSString *)encoded
{
    /* First valid character that can be indexed in decode lookup table */
    static int charDigitsBase = '2';

    /* Lookup table used to decode() characters in encoded strings */
    static int charDigits[] =
    {   26,27,28,29,30,31,-1,-1,-1,-1,-1,-1,-1,-1 //   23456789:;<=>?
        ,-1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14 // @ABCDEFGHIJKLMNO
        ,15,16,17,18,19,20,21,22,23,24,25,-1,-1,-1,-1,-1 // PQRSTUVWXYZ[\]^_
        ,-1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14 // `abcdefghijklmno
        ,15,16,17,18,19,20,21,22,23,24,25                // pqrstuvwxyz
    };

    if (! [encoded canBeConvertedToEncoding:NSASCIIStringEncoding]) return nil;
    const char *chars = [encoded cStringUsingEncoding:NSASCIIStringEncoding]; // avoids using characterAtIndex.
    int charsLen = [encoded lengthOfBytesUsingEncoding:NSASCIIStringEncoding];

    // Note that the code below could detect non canonical Base32 length within the loop. However canonical Base32 length can be tested before entering the loop.
    // A canonical Base32 length modulo 8 cannot be:
    // 1 (aborts discarding 5 bits at STEP n=0 which produces no byte),
    // 3 (aborts discarding 7 bits at STEP n=2 which produces no byte),
    // 6 (aborts discarding 6 bits at STEP n=1 which produces no byte).
    switch (charsLen & 7) { // test the length of last subblock
        case 1: //  5 bits in subblock:  0 useful bits but 5 discarded
        case 3: // 15 bits in subblock:  8 useful bits but 7 discarded
        case 6: // 30 bits in subblock: 24 useful bits but 6 discarded
            return nil; // non-canonical length
    }
    int charDigitsLen = sizeof(charDigits);
    int bytesLen = (charsLen * 5) >> 3;
    Byte bytes[bytesLen];
    int bytesOffset = 0, charsOffset = 0;
    // Also the code below does test that other discarded bits
    // (1 to 4 bits at end) are effectively 0.
    while (charsLen > 0)
    {
        int digit, lastDigit;
        // STEP n = 0: Read the 1st Char in a 8-Chars subblock
        // Leave 5 bits, asserting there's another encoding Char
        if ((digit = (int)chars[charsOffset] - charDigitsBase) < 0 || digit >= charDigitsLen || (digit = charDigits[digit]) == -1)
            return nil; // invalid character
        lastDigit = digit << 3;
        // STEP n = 5: Read the 2nd Char in a 8-Chars subblock
        // Insert 3 bits, leave 2 bits, possibly trailing if no more Char
        if ((digit = (int)chars[charsOffset + 1] - charDigitsBase) < 0 || digit >= charDigitsLen || (digit = charDigits[digit]) == -1)
            return nil; // invalid character
        bytes[bytesOffset] = (Byte)((digit >> 2) | lastDigit);
        lastDigit = (digit & 3) << 6;
        if (charsLen == 2) {
            if (lastDigit != 0) return nil; // non-canonical end
            break; // discard the 2 trailing null bits
        }
        // STEP n = 2: Read the 3rd Char in a 8-Chars subblock
        // Leave 7 bits, asserting there's another encoding Char
        if ((digit = (int)chars[charsOffset + 2] - charDigitsBase) < 0 || digit >= charDigitsLen || (digit = charDigits[digit]) == -1)
            return nil; // invalid character
        lastDigit |= (Byte)(digit << 1);
        // STEP n = 7: Read the 4th Char in a 8-chars Subblock
        // Insert 1 bit, leave 4 bits, possibly trailing if no more Char
        if ((digit = (int)chars[charsOffset + 3] - charDigitsBase) < 0 || digit >= charDigitsLen || (digit = charDigits[digit]) == -1)
            return nil; // invalid character
        bytes[bytesOffset + 1] = (Byte)((digit >> 4) | lastDigit);
        lastDigit = (Byte)((digit & 15) << 4);
        if (charsLen == 4) {
            if (lastDigit != 0) return nil; // non-canonical end
            break; // discard the 4 trailing null bits
        }
        // STEP n = 4: Read the 5th Char in a 8-Chars subblock
        // Insert 4 bits, leave 1 bit, possibly trailing if no more Char
        if ((digit = (int)chars[charsOffset + 4] - charDigitsBase) < 0 || digit >= charDigitsLen || (digit = charDigits[digit]) == -1)
            return nil; // invalid character
        bytes[bytesOffset + 2] = (Byte)((digit >> 1) | lastDigit);
        lastDigit = (Byte)((digit & 1) << 7);
        if (charsLen == 5) {
            if (lastDigit != 0) return nil; // non-canonical end
            break; // discard the 1 trailing null bit
        }
        // STEP n = 1: Read the 6th Char in a 8-Chars subblock
        // Leave 6 bits, asserting there's another encoding Char
        if ((digit = (int)chars[charsOffset + 5] - charDigitsBase) < 0 || digit >= charDigitsLen || (digit = charDigits[digit]) == -1)
            return nil; // invalid character
        lastDigit |= (Byte)(digit << 2);
        // STEP n = 6: Read the 7th Char in a 8-Chars subblock
        // Insert 2 bits, leave 3 bits, possibly trailing if no more Char
        if ((digit = (int)chars[charsOffset + 6] - charDigitsBase) < 0 || digit >= charDigitsLen || (digit = charDigits[digit]) == -1)
            return nil; // invalid character
        bytes[bytesOffset + 3] = (Byte)((digit >> 3) | lastDigit);
        lastDigit = (Byte)((digit & 7) << 5);
        if (charsLen == 7) {
            if (lastDigit != 0) return nil; // non-canonical end
            break; // discard the 3 trailing null bits
        }
        // STEP n = 3: Read the 8th Char in a 8-Chars subblock
        // Insert 5 bits, leave 0 bit, next encoding Char may not exist
        if ((digit = (int)chars[charsOffset + 7] - charDigitsBase) < 0 || digit >= charDigitsLen || (digit = charDigits[digit]) == -1)
            return nil; // invalid character
        bytes[bytesOffset + 4] = (Byte)(digit | lastDigit);
        //// This point is always reached for chars.length multiple of 8
        charsOffset += 8;
        bytesOffset += 5;
        charsLen -= 8;
    }
    // On loop exit, discard the n trailing null bits
    return [NSData dataWithBytes:bytes length:sizeof(bytes)];
}

- (NSString *) base32String
{
    /* Lookup table used to canonically encode() groups of data bits */
    static char canonicalChars[] =
    {   'A','B','C','D','E','F','G','H','I','J','K','L','M' // 00..12
        ,'N','O','P','Q','R','S','T','U','V','W','X','Y','Z' // 13..25
        ,'2','3','4','5','6','7'                             // 26..31
    };
    const Byte *bytes = [self bytes];
    int bytesOffset = 0, bytesLen = [self length];
    int charsOffset = 0, charsLen = ((bytesLen << 3) + 4) / 5;
    char chars[charsLen];
    while (bytesLen != 0) {
        int digit, lastDigit;
        // INVARIANTS FOR EACH STEP n in [0..5[; digit in [0..31[;
        // The remaining n bits are already aligned on top positions
        // of the 5 least bits of digit, the other bits are 0.
        ////// STEP n = 0: insert new 5 bits, leave 3 bits
        digit = bytes[bytesOffset] & 255;
        chars[charsOffset] = canonicalChars[digit >> 3];
        lastDigit = (digit & 7) << 2;
        if (bytesLen == 1) { // put the last 3 bits
            chars[charsOffset + 1] = canonicalChars[lastDigit];
            break;
        }
        ////// STEP n = 3: insert 2 new bits, then 5 bits, leave 1 bit
        digit = bytes[bytesOffset + 1] & 255;
        chars[charsOffset + 1] = canonicalChars[(digit >> 6) | lastDigit];
        chars[charsOffset + 2] = canonicalChars[(digit >> 1) & 31];
        lastDigit = (digit & 1) << 4;
        if (bytesLen == 2) { // put the last 1 bit
            chars[charsOffset + 3] = canonicalChars[lastDigit];
            break;
        }
        ////// STEP n = 1: insert 4 new bits, leave 4 bit
        digit = bytes[bytesOffset + 2] & 255;
        chars[charsOffset + 3] = canonicalChars[(digit >> 4) | lastDigit];
        lastDigit = (digit & 15) << 1;
        if (bytesLen == 3) { // put the last 1 bits
            chars[charsOffset + 4] = canonicalChars[lastDigit];
            break;
        }
        ////// STEP n = 4: insert 1 new bit, then 5 bits, leave 2 bits
        digit = bytes[bytesOffset + 3] & 255;
        chars[charsOffset + 4] = canonicalChars[(digit >> 7) | lastDigit];
        chars[charsOffset + 5] = canonicalChars[(digit >> 2) & 31];
        lastDigit = (digit & 3) << 3;
        if (bytesLen == 4) { // put the last 2 bits
            chars[charsOffset + 6] = canonicalChars[lastDigit];
            break;
        }
        ////// STEP n = 2: insert 3 new bits, then 5 bits, leave 0 bit
        digit = bytes[bytesOffset + 4] & 255;
        chars[charsOffset + 6] = canonicalChars[(digit >> 5) | lastDigit];
        chars[charsOffset + 7] = canonicalChars[digit & 31];
        //// This point is always reached for bytes.length multiple of 5
        bytesOffset += 5;
        charsOffset += 8;
        bytesLen -= 5;
    }
    return [NSString stringWithCString:chars length:sizeof(chars)];
}

#define FinishBlock(X) \
(*code_ptr = (X), \
code_ptr = dst++, \
code = 0x01)

- (NSData *) encodeCOBS
{
    if ([self length] == 0) return self;

    NSMutableData *encoded = [NSMutableData dataWithLength:([self length] + [self length] / 254 + 1)];
    unsigned char *dst = [encoded mutableBytes];
    const unsigned char *ptr = [self bytes];
    unsigned long length = [self length];
    const unsigned char *end = ptr + length;
    unsigned char *code_ptr = dst++;
    unsigned char code = 0x01;
    while (ptr < end)
    {
        if (*ptr == 0) FinishBlock(code);
        else
        {
            *dst++ = *ptr;
            code++;
            if (code == 0xFF) FinishBlock(code);
        }
        ptr++;
    }
    FinishBlock(code);

    [encoded setLength:((Byte *)dst - (Byte *)[encoded mutableBytes])];
    return [NSData dataWithData:encoded];
}

- (NSData *) decodeCOBS
{
    if ([self length] == 0) return self;

    const Byte *ptr = [self bytes];
    unsigned length = [self length];
    NSMutableData *decoded = [NSMutableData dataWithLength:length];
    Byte *dst = [decoded mutableBytes];
    Byte *basedst = dst;

    const unsigned char *end = ptr + length;
    while (ptr < end)
    {
        int i, code = *ptr++;
        for (i=1; i<code; i++) *dst++ = *ptr++;
        if (code < 0xFF) *dst++ = 0;
    }

    [decoded setLength:(dst - basedst)];
    return [NSData dataWithData:decoded];
}

- (NSData *)zlibInflate
{
    if ([self length] == 0) return self;

    unsigned full_length = [self length];
    unsigned half_length = [self length] / 2;

    NSMutableData *decompressed = [NSMutableData dataWithLength: full_length + half_length];
    BOOL done = NO;
    int status;

    z_stream strm;
    strm.next_in = (Bytef *)[self bytes];
    strm.avail_in = [self length];
    strm.total_out = 0;
    strm.zalloc = Z_NULL;
    strm.zfree = Z_NULL;

    if (inflateInit (&strm) != 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 *)zlibDeflate
{
    if ([self length] == 0) return self;

    z_stream strm;

    strm.zalloc = Z_NULL;
    strm.zfree = Z_NULL;
    strm.opaque = Z_NULL;
    strm.total_out = 0;
    strm.next_in=(Bytef *)[self bytes];
    strm.avail_in = [self length];

    // Compresssion Levels:
    //   Z_NO_COMPRESSION
    //   Z_BEST_SPEED
    //   Z_BEST_COMPRESSION
    //   Z_DEFAULT_COMPRESSION

    if (deflateInit(&strm, Z_DEFAULT_COMPRESSION) != Z_OK) return nil;

    NSMutableData *compressed = [NSMutableData dataWithLength:16384];  // 16K chuncks 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];
}

- (NSData *)gzipInflate
{
    if ([self length] == 0) return self;

    unsigned full_length = [self length];
    unsigned half_length = [self length] / 2;

    NSMutableData *decompressed = [NSMutableData dataWithLength: full_length + half_length];
    BOOL done = NO;
    int status;

    z_stream strm;
    strm.next_in = (Bytef *)[self bytes];
    strm.avail_in = [self 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
{
    if ([self length] == 0) return self;

    z_stream strm;

    strm.zalloc = Z_NULL;
    strm.zfree = Z_NULL;
    strm.opaque = Z_NULL;
    strm.total_out = 0;
    strm.next_in=(Bytef *)[self bytes];
    strm.avail_in = [self 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];
}

// --------------------------------CRC32-------------------------------
static const unsigned long crc32table[] =
{
    0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3,
    0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91,
    0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
    0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5,
    0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
    0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
    0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f,
    0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d,
    0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
    0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
    0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457,
    0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
    0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb,
    0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9,
    0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
    0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad,
    0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683,
    0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
    0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7,
    0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
    0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
    0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79,
    0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f,
    0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
    0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
    0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21,
    0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
    0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45,
    0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db,
    0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
    0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf,
    0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
};

- (unsigned int)crc32
{
    unsigned int    crcval;
    unsigned int    x, y;
    const void      *bytes;
    unsigned int    max;

    bytes = [self bytes];
    max = [self length];
    crcval = 0xffffffff;
    for (x = 0, y = max; x < y; x++) {
        crcval = ((crcval >> 8) & 0x00ffffff) ^ crc32table[(crcval ^ (*((unsigned char *)bytes + x))) & 0xff];
    }

    return crcval ^ 0xffffffff;
}

// Hash function, by [[DamienBob]]

#define HEComputeDigest(method)                     \
method##_CTX ctx;                               \
unsigned char digest[method##_DIGEST_LENGTH];       \
method##_Init(&ctx);                            \
method##_Update(&ctx, [self bytes], [self length]);     \
method##_Final(digest, &ctx);

#define HEComputeDigestNSData(method)               \
HEComputeDigest(method)                     \
return [NSData dataWithBytes:digest length:method##_DIGEST_LENGTH];

#define HEComputeDigestNSString(method)             \
static char __HEHexDigits[] = "0123456789abcdef";       \
unsigned char digestString[2*method##_DIGEST_LENGTH];\
unsigned int i;                                 \
HEComputeDigest(method)                     \
for(i=0; i<method##_DIGEST_LENGTH; i++) {               \
    digestString[2*i]   = __HEHexDigits[digest[i] >> 4];    \
    digestString[2*i+1] = __HEHexDigits[digest[i] & 0x0f];\
}                                           \
return [NSString stringWithCString:(char *)digestString length:2*method##_DIGEST_LENGTH];

#define SHA1_CTX                SHA_CTX
#define SHA1_DIGEST_LENGTH      SHA_DIGEST_LENGTH

- (NSData*) md5Digest
{
    HEComputeDigestNSData(MD5);
}

- (NSString*) md5DigestString
{
    HEComputeDigestNSString(MD5);
}

- (NSData*) sha1Digest
{
    HEComputeDigestNSData(SHA1);
}

- (NSString*) sha1DigestString
{
    HEComputeDigestNSString(SHA1);
}

- (NSData*) ripemd160Digest
{
    HEComputeDigestNSData(RIPEMD160);
}

- (NSString*) ripemd160DigestString
{
    HEComputeDigestNSString(RIPEMD160);
}

@end

If you store the data for the conversations in an NSData object, the folks at the CocoaDev wiki have posted an NSData category that adds gzip and zlib compression / decompression as simple methods. These have worked well for me in my iPhone application.

As the above link has gone dead while the CocoaDev wiki is being moved to a new host, I've reproduced this category in its entirety below.

Interface:

@interface NSData (NSDataExtension)

// Returns range [start, null byte), or (NSNotFound, 0).
- (NSRange) rangeOfNullTerminatedBytesFrom:(int)start;

// Canonical Base32 encoding/decoding.
+ (NSData *) dataWithBase32String:(NSString *)base32;
- (NSString *) base32String;

// COBS is an encoding that eliminates 0x00.
- (NSData *) encodeCOBS;
- (NSData *) decodeCOBS;

// ZLIB
- (NSData *) zlibInflate;
- (NSData *) zlibDeflate;

// GZIP
- (NSData *) gzipInflate;
- (NSData *) gzipDeflate;

//CRC32
- (unsigned int)crc32;

// Hash
- (NSData*) md5Digest;
- (NSString*) md5DigestString;
- (NSData*) sha1Digest;
- (NSString*) sha1DigestString;
- (NSData*) ripemd160Digest;
- (NSString*) ripemd160DigestString;

@end

Implementation:

#import "NSData+CocoaDevUsersAdditions.h"
#include <zlib.h>
#include <openssl/md5.h>
#include <openssl/sha.h>
#include <openssl/ripemd.h>


@implementation NSData (NSDataExtension)

// Returns range [start, null byte), or (NSNotFound, 0).
- (NSRange) rangeOfNullTerminatedBytesFrom:(int)start
{
    const Byte *pdata = [self bytes];
    int len = [self length];
    if (start < len)
    {
        const Byte *end = memchr (pdata + start, 0x00, len - start);
        if (end != NULL) return NSMakeRange (start, end - (pdata + start));
    }
    return NSMakeRange (NSNotFound, 0);
}

+ (NSData *) dataWithBase32String:(NSString *)encoded
{
    /* First valid character that can be indexed in decode lookup table */
    static int charDigitsBase = '2';

    /* Lookup table used to decode() characters in encoded strings */
    static int charDigits[] =
    {   26,27,28,29,30,31,-1,-1,-1,-1,-1,-1,-1,-1 //   23456789:;<=>?
        ,-1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14 // @ABCDEFGHIJKLMNO
        ,15,16,17,18,19,20,21,22,23,24,25,-1,-1,-1,-1,-1 // PQRSTUVWXYZ[\]^_
        ,-1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14 // `abcdefghijklmno
        ,15,16,17,18,19,20,21,22,23,24,25                // pqrstuvwxyz
    };

    if (! [encoded canBeConvertedToEncoding:NSASCIIStringEncoding]) return nil;
    const char *chars = [encoded cStringUsingEncoding:NSASCIIStringEncoding]; // avoids using characterAtIndex.
    int charsLen = [encoded lengthOfBytesUsingEncoding:NSASCIIStringEncoding];

    // Note that the code below could detect non canonical Base32 length within the loop. However canonical Base32 length can be tested before entering the loop.
    // A canonical Base32 length modulo 8 cannot be:
    // 1 (aborts discarding 5 bits at STEP n=0 which produces no byte),
    // 3 (aborts discarding 7 bits at STEP n=2 which produces no byte),
    // 6 (aborts discarding 6 bits at STEP n=1 which produces no byte).
    switch (charsLen & 7) { // test the length of last subblock
        case 1: //  5 bits in subblock:  0 useful bits but 5 discarded
        case 3: // 15 bits in subblock:  8 useful bits but 7 discarded
        case 6: // 30 bits in subblock: 24 useful bits but 6 discarded
            return nil; // non-canonical length
    }
    int charDigitsLen = sizeof(charDigits);
    int bytesLen = (charsLen * 5) >> 3;
    Byte bytes[bytesLen];
    int bytesOffset = 0, charsOffset = 0;
    // Also the code below does test that other discarded bits
    // (1 to 4 bits at end) are effectively 0.
    while (charsLen > 0)
    {
        int digit, lastDigit;
        // STEP n = 0: Read the 1st Char in a 8-Chars subblock
        // Leave 5 bits, asserting there's another encoding Char
        if ((digit = (int)chars[charsOffset] - charDigitsBase) < 0 || digit >= charDigitsLen || (digit = charDigits[digit]) == -1)
            return nil; // invalid character
        lastDigit = digit << 3;
        // STEP n = 5: Read the 2nd Char in a 8-Chars subblock
        // Insert 3 bits, leave 2 bits, possibly trailing if no more Char
        if ((digit = (int)chars[charsOffset + 1] - charDigitsBase) < 0 || digit >= charDigitsLen || (digit = charDigits[digit]) == -1)
            return nil; // invalid character
        bytes[bytesOffset] = (Byte)((digit >> 2) | lastDigit);
        lastDigit = (digit & 3) << 6;
        if (charsLen == 2) {
            if (lastDigit != 0) return nil; // non-canonical end
            break; // discard the 2 trailing null bits
        }
        // STEP n = 2: Read the 3rd Char in a 8-Chars subblock
        // Leave 7 bits, asserting there's another encoding Char
        if ((digit = (int)chars[charsOffset + 2] - charDigitsBase) < 0 || digit >= charDigitsLen || (digit = charDigits[digit]) == -1)
            return nil; // invalid character
        lastDigit |= (Byte)(digit << 1);
        // STEP n = 7: Read the 4th Char in a 8-chars Subblock
        // Insert 1 bit, leave 4 bits, possibly trailing if no more Char
        if ((digit = (int)chars[charsOffset + 3] - charDigitsBase) < 0 || digit >= charDigitsLen || (digit = charDigits[digit]) == -1)
            return nil; // invalid character
        bytes[bytesOffset + 1] = (Byte)((digit >> 4) | lastDigit);
        lastDigit = (Byte)((digit & 15) << 4);
        if (charsLen == 4) {
            if (lastDigit != 0) return nil; // non-canonical end
            break; // discard the 4 trailing null bits
        }
        // STEP n = 4: Read the 5th Char in a 8-Chars subblock
        // Insert 4 bits, leave 1 bit, possibly trailing if no more Char
        if ((digit = (int)chars[charsOffset + 4] - charDigitsBase) < 0 || digit >= charDigitsLen || (digit = charDigits[digit]) == -1)
            return nil; // invalid character
        bytes[bytesOffset + 2] = (Byte)((digit >> 1) | lastDigit);
        lastDigit = (Byte)((digit & 1) << 7);
        if (charsLen == 5) {
            if (lastDigit != 0) return nil; // non-canonical end
            break; // discard the 1 trailing null bit
        }
        // STEP n = 1: Read the 6th Char in a 8-Chars subblock
        // Leave 6 bits, asserting there's another encoding Char
        if ((digit = (int)chars[charsOffset + 5] - charDigitsBase) < 0 || digit >= charDigitsLen || (digit = charDigits[digit]) == -1)
            return nil; // invalid character
        lastDigit |= (Byte)(digit << 2);
        // STEP n = 6: Read the 7th Char in a 8-Chars subblock
        // Insert 2 bits, leave 3 bits, possibly trailing if no more Char
        if ((digit = (int)chars[charsOffset + 6] - charDigitsBase) < 0 || digit >= charDigitsLen || (digit = charDigits[digit]) == -1)
            return nil; // invalid character
        bytes[bytesOffset + 3] = (Byte)((digit >> 3) | lastDigit);
        lastDigit = (Byte)((digit & 7) << 5);
        if (charsLen == 7) {
            if (lastDigit != 0) return nil; // non-canonical end
            break; // discard the 3 trailing null bits
        }
        // STEP n = 3: Read the 8th Char in a 8-Chars subblock
        // Insert 5 bits, leave 0 bit, next encoding Char may not exist
        if ((digit = (int)chars[charsOffset + 7] - charDigitsBase) < 0 || digit >= charDigitsLen || (digit = charDigits[digit]) == -1)
            return nil; // invalid character
        bytes[bytesOffset + 4] = (Byte)(digit | lastDigit);
        //// This point is always reached for chars.length multiple of 8
        charsOffset += 8;
        bytesOffset += 5;
        charsLen -= 8;
    }
    // On loop exit, discard the n trailing null bits
    return [NSData dataWithBytes:bytes length:sizeof(bytes)];
}

- (NSString *) base32String
{
    /* Lookup table used to canonically encode() groups of data bits */
    static char canonicalChars[] =
    {   'A','B','C','D','E','F','G','H','I','J','K','L','M' // 00..12
        ,'N','O','P','Q','R','S','T','U','V','W','X','Y','Z' // 13..25
        ,'2','3','4','5','6','7'                             // 26..31
    };
    const Byte *bytes = [self bytes];
    int bytesOffset = 0, bytesLen = [self length];
    int charsOffset = 0, charsLen = ((bytesLen << 3) + 4) / 5;
    char chars[charsLen];
    while (bytesLen != 0) {
        int digit, lastDigit;
        // INVARIANTS FOR EACH STEP n in [0..5[; digit in [0..31[;
        // The remaining n bits are already aligned on top positions
        // of the 5 least bits of digit, the other bits are 0.
        ////// STEP n = 0: insert new 5 bits, leave 3 bits
        digit = bytes[bytesOffset] & 255;
        chars[charsOffset] = canonicalChars[digit >> 3];
        lastDigit = (digit & 7) << 2;
        if (bytesLen == 1) { // put the last 3 bits
            chars[charsOffset + 1] = canonicalChars[lastDigit];
            break;
        }
        ////// STEP n = 3: insert 2 new bits, then 5 bits, leave 1 bit
        digit = bytes[bytesOffset + 1] & 255;
        chars[charsOffset + 1] = canonicalChars[(digit >> 6) | lastDigit];
        chars[charsOffset + 2] = canonicalChars[(digit >> 1) & 31];
        lastDigit = (digit & 1) << 4;
        if (bytesLen == 2) { // put the last 1 bit
            chars[charsOffset + 3] = canonicalChars[lastDigit];
            break;
        }
        ////// STEP n = 1: insert 4 new bits, leave 4 bit
        digit = bytes[bytesOffset + 2] & 255;
        chars[charsOffset + 3] = canonicalChars[(digit >> 4) | lastDigit];
        lastDigit = (digit & 15) << 1;
        if (bytesLen == 3) { // put the last 1 bits
            chars[charsOffset + 4] = canonicalChars[lastDigit];
            break;
        }
        ////// STEP n = 4: insert 1 new bit, then 5 bits, leave 2 bits
        digit = bytes[bytesOffset + 3] & 255;
        chars[charsOffset + 4] = canonicalChars[(digit >> 7) | lastDigit];
        chars[charsOffset + 5] = canonicalChars[(digit >> 2) & 31];
        lastDigit = (digit & 3) << 3;
        if (bytesLen == 4) { // put the last 2 bits
            chars[charsOffset + 6] = canonicalChars[lastDigit];
            break;
        }
        ////// STEP n = 2: insert 3 new bits, then 5 bits, leave 0 bit
        digit = bytes[bytesOffset + 4] & 255;
        chars[charsOffset + 6] = canonicalChars[(digit >> 5) | lastDigit];
        chars[charsOffset + 7] = canonicalChars[digit & 31];
        //// This point is always reached for bytes.length multiple of 5
        bytesOffset += 5;
        charsOffset += 8;
        bytesLen -= 5;
    }
    return [NSString stringWithCString:chars length:sizeof(chars)];
}

#define FinishBlock(X) \
(*code_ptr = (X), \
code_ptr = dst++, \
code = 0x01)

- (NSData *) encodeCOBS
{
    if ([self length] == 0) return self;

    NSMutableData *encoded = [NSMutableData dataWithLength:([self length] + [self length] / 254 + 1)];
    unsigned char *dst = [encoded mutableBytes];
    const unsigned char *ptr = [self bytes];
    unsigned long length = [self length];
    const unsigned char *end = ptr + length;
    unsigned char *code_ptr = dst++;
    unsigned char code = 0x01;
    while (ptr < end)
    {
        if (*ptr == 0) FinishBlock(code);
        else
        {
            *dst++ = *ptr;
            code++;
            if (code == 0xFF) FinishBlock(code);
        }
        ptr++;
    }
    FinishBlock(code);

    [encoded setLength:((Byte *)dst - (Byte *)[encoded mutableBytes])];
    return [NSData dataWithData:encoded];
}

- (NSData *) decodeCOBS
{
    if ([self length] == 0) return self;

    const Byte *ptr = [self bytes];
    unsigned length = [self length];
    NSMutableData *decoded = [NSMutableData dataWithLength:length];
    Byte *dst = [decoded mutableBytes];
    Byte *basedst = dst;

    const unsigned char *end = ptr + length;
    while (ptr < end)
    {
        int i, code = *ptr++;
        for (i=1; i<code; i++) *dst++ = *ptr++;
        if (code < 0xFF) *dst++ = 0;
    }

    [decoded setLength:(dst - basedst)];
    return [NSData dataWithData:decoded];
}

- (NSData *)zlibInflate
{
    if ([self length] == 0) return self;

    unsigned full_length = [self length];
    unsigned half_length = [self length] / 2;

    NSMutableData *decompressed = [NSMutableData dataWithLength: full_length + half_length];
    BOOL done = NO;
    int status;

    z_stream strm;
    strm.next_in = (Bytef *)[self bytes];
    strm.avail_in = [self length];
    strm.total_out = 0;
    strm.zalloc = Z_NULL;
    strm.zfree = Z_NULL;

    if (inflateInit (&strm) != 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 *)zlibDeflate
{
    if ([self length] == 0) return self;

    z_stream strm;

    strm.zalloc = Z_NULL;
    strm.zfree = Z_NULL;
    strm.opaque = Z_NULL;
    strm.total_out = 0;
    strm.next_in=(Bytef *)[self bytes];
    strm.avail_in = [self length];

    // Compresssion Levels:
    //   Z_NO_COMPRESSION
    //   Z_BEST_SPEED
    //   Z_BEST_COMPRESSION
    //   Z_DEFAULT_COMPRESSION

    if (deflateInit(&strm, Z_DEFAULT_COMPRESSION) != Z_OK) return nil;

    NSMutableData *compressed = [NSMutableData dataWithLength:16384];  // 16K chuncks 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];
}

- (NSData *)gzipInflate
{
    if ([self length] == 0) return self;

    unsigned full_length = [self length];
    unsigned half_length = [self length] / 2;

    NSMutableData *decompressed = [NSMutableData dataWithLength: full_length + half_length];
    BOOL done = NO;
    int status;

    z_stream strm;
    strm.next_in = (Bytef *)[self bytes];
    strm.avail_in = [self 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
{
    if ([self length] == 0) return self;

    z_stream strm;

    strm.zalloc = Z_NULL;
    strm.zfree = Z_NULL;
    strm.opaque = Z_NULL;
    strm.total_out = 0;
    strm.next_in=(Bytef *)[self bytes];
    strm.avail_in = [self 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];
}

// --------------------------------CRC32-------------------------------
static const unsigned long crc32table[] =
{
    0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3,
    0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91,
    0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
    0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5,
    0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
    0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
    0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f,
    0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d,
    0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
    0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
    0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457,
    0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
    0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb,
    0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9,
    0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
    0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad,
    0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683,
    0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
    0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7,
    0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
    0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
    0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79,
    0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f,
    0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
    0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
    0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21,
    0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
    0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45,
    0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db,
    0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
    0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf,
    0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
};

- (unsigned int)crc32
{
    unsigned int    crcval;
    unsigned int    x, y;
    const void      *bytes;
    unsigned int    max;

    bytes = [self bytes];
    max = [self length];
    crcval = 0xffffffff;
    for (x = 0, y = max; x < y; x++) {
        crcval = ((crcval >> 8) & 0x00ffffff) ^ crc32table[(crcval ^ (*((unsigned char *)bytes + x))) & 0xff];
    }

    return crcval ^ 0xffffffff;
}

// Hash function, by [[DamienBob]]

#define HEComputeDigest(method)                     \
method##_CTX ctx;                               \
unsigned char digest[method##_DIGEST_LENGTH];       \
method##_Init(&ctx);                            \
method##_Update(&ctx, [self bytes], [self length]);     \
method##_Final(digest, &ctx);

#define HEComputeDigestNSData(method)               \
HEComputeDigest(method)                     \
return [NSData dataWithBytes:digest length:method##_DIGEST_LENGTH];

#define HEComputeDigestNSString(method)             \
static char __HEHexDigits[] = "0123456789abcdef";       \
unsigned char digestString[2*method##_DIGEST_LENGTH];\
unsigned int i;                                 \
HEComputeDigest(method)                     \
for(i=0; i<method##_DIGEST_LENGTH; i++) {               \
    digestString[2*i]   = __HEHexDigits[digest[i] >> 4];    \
    digestString[2*i+1] = __HEHexDigits[digest[i] & 0x0f];\
}                                           \
return [NSString stringWithCString:(char *)digestString length:2*method##_DIGEST_LENGTH];

#define SHA1_CTX                SHA_CTX
#define SHA1_DIGEST_LENGTH      SHA_DIGEST_LENGTH

- (NSData*) md5Digest
{
    HEComputeDigestNSData(MD5);
}

- (NSString*) md5DigestString
{
    HEComputeDigestNSString(MD5);
}

- (NSData*) sha1Digest
{
    HEComputeDigestNSData(SHA1);
}

- (NSString*) sha1DigestString
{
    HEComputeDigestNSString(SHA1);
}

- (NSData*) ripemd160Digest
{
    HEComputeDigestNSData(RIPEMD160);
}

- (NSString*) ripemd160DigestString
{
    HEComputeDigestNSString(RIPEMD160);
}

@end
禾厶谷欠 2024-07-15 12:02:59

zlib 和 bzip2 可用。 您可以随时添加其他文件,只要它们(通常)在 OS X 下编译即可。

对于最小文件大小,bzip2 是更好的选择,但需要更多的 CPU 能力来压缩和解压缩。

另外,由于您正在与网络服务通信,因此您可能不需要做太多事情。 NSURLRequest 在服务器响应中接受 gzip 编码透明。

zlib and bzip2 are available. And you can always add others, as long as they'll (generally) compile under OS X.

bzip2 is a better choice for smallest file sizes, but requires much more CPU power to compress and decompress.

Also, since you're talking to a web service, you may not have to do much. NSURLRequest accepts gzip encoding transparently in server responses.

魂牵梦绕锁你心扉 2024-07-15 12:02:59

Apple 的内置 libcompression 现在可用于 iOS 9。下面显示了用于压缩 NSData 的 compression_encode_buffer 的简短示例。

@import Compression;

NSData *theData = [NSData dataWithContentsOfFile:[<some file> path]];
size_t theDataSize = [theData length];
const uint8_t *buf = (const uint8_t *)[theData bytes];
uint8_t *destBuf = malloc(sizeof(uint8_t) * theDataSize);
size_t compressedSize = compression_encode_buffer(destBuf, theDataSize, buf, theDataSize, NULL, COMPRESSION_LZFSE);
self.<NSData item> = [NSData dataWithBytes:destBuf length:compressedSize];

NSLog(@"originalsize:%zu compressed:%zu", theDataSize, compressedSize);
free(destBuf);

有多种不同的算法可供使用:

  • LZMA
  • LZ4
  • ZLIB
  • LZFSE

块压缩或流压缩均受支持。

请参阅 https://developer.apple.com/library/mac/documentation /性能/参考/压缩/

Apple's built in libcompression is now available for iOS 9. A short example of compression_encode_buffer is shown below for compressing NSData.

@import Compression;

NSData *theData = [NSData dataWithContentsOfFile:[<some file> path]];
size_t theDataSize = [theData length];
const uint8_t *buf = (const uint8_t *)[theData bytes];
uint8_t *destBuf = malloc(sizeof(uint8_t) * theDataSize);
size_t compressedSize = compression_encode_buffer(destBuf, theDataSize, buf, theDataSize, NULL, COMPRESSION_LZFSE);
self.<NSData item> = [NSData dataWithBytes:destBuf length:compressedSize];

NSLog(@"originalsize:%zu compressed:%zu", theDataSize, compressedSize);
free(destBuf);

A number of different algorithms are available:

  • LZMA
  • LZ4
  • ZLIB
  • LZFSE

Block compression or stream compression are both supported.

See https://developer.apple.com/library/mac/documentation/Performance/Reference/Compression/

月光色 2024-07-15 12:02:59

如果您只有压缩数据并且知道未压缩的大小,您可以使用:

#import "zlib.h"


int datal = [zipedData length];
Bytef *buffer[uncompressedSize];
Bytef *dataa[datal];

[zipedData getBytes:dataa];

Long *ld;

uLong sl = datal;
*ld = uncompressedSize;
if(uncompress(buffer, ld, dataa, sl) == Z_OK)
{
NSData *uncompressedData = [NSData dataWithBytes:buffer length:uncompressedSize];
NSString *txtFile = [[NSString alloc] initWithData:uncompressedData encoding:NSUTF8StringEncoding];
}

If you have only compressed data and know uncompressed size you can use:

#import "zlib.h"


int datal = [zipedData length];
Bytef *buffer[uncompressedSize];
Bytef *dataa[datal];

[zipedData getBytes:dataa];

Long *ld;

uLong sl = datal;
*ld = uncompressedSize;
if(uncompress(buffer, ld, dataa, sl) == Z_OK)
{
NSData *uncompressedData = [NSData dataWithBytes:buffer length:uncompressedSize];
NSString *txtFile = [[NSString alloc] initWithData:uncompressedData encoding:NSUTF8StringEncoding];
}
╭ゆ眷念 2024-07-15 12:02:59

我相信 zlib 在手机上可用。

I believe zlib is available on the phone.

带刺的爱情 2024-07-15 12:02:59

相信我,最好的选择是使用 ZipArchive,请参阅:如何解压缩 AES -256 加密的 Zip 文件?

准备好在需要时寻求帮助。

trust me the best choice is to use ZipArchive see: How to decompress an AES-256 encrypted Zip file?

ready for help if needed.

汹涌人海 2024-07-15 12:02:59

Objective-Zip 是另一种选择。 请参阅这些优秀的说明

注意我必须使用 XCode->Edit->Refactor->Convert to Objective C ARC 将源代码转换为使用 ARC。

Objective-Zip is another option. See these excellent instructions.

Note I had to convert the source code to use ARC by using the XCode->Edit->Refactor->Convert to Objective C ARC.

傲世九天 2024-07-15 12:02:59

NSURL 表示它支持 gzip 编码,因此您只需让 RESTful Web 服务在适当的时候返回 gzip 编码内容即可。 所有解码都将在幕后完成。

NSURL says it supports the gzip encoding so you shouldn't have to do anything more than have your RESTful web service return gzip encoded content when appropriate. All the decoding will be done under the covers.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文