iPhone上的压缩API

有没有一个可用于iPhone的压缩API? 我们正在为我们的iPhone应用程序构build一些RESTful Web服务进行交谈,但我们希望至less压缩一些对话以提高效率。

我不在乎格式(ZIP,LHA,什么)的格式,也不需要保密。

一些受访者指出,服务器可以压缩其输出,iPhone可以消耗。 我们的情况恰恰相反。 我们将压缩内容发布 Web服务。 我们不关心按照其他方式压缩。

zlib和bzip2可用。 你可以随时添加其他的,只要他们(一般)在OS X下编译。

对于最小的文件大小,bzip2是一个更好的select,但需要更多的CPU功率来压缩和解压缩。

另外,由于您正在与Web服务交谈,您可能不需要做太多的事情。 NSURLRequest在服务器响应中透明地接受gzip编码

如果您将对话的数据存储在一个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 

苹果的内置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); 

有许多不同的algorithm可用:

  • LZMA
  • LZ4
  • ZLIB
  • LZFSE

块压缩或stream压缩都支持。

请参阅https://developer.apple.com/library/mac/documentation/Performance/Reference/Compression/

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

 #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]; } 

我相信zlib可以在手机上使用。

相信我最好的select是使用ZipArchive请参阅: 如何解压缩AES-256encryptionZip文件?

准备好如果需要帮助。

Objective-Zip是另一种select。 看到这些优秀的指示 。

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

NSURL表示它支持gzip编码,所以你不需要做任何事情,只要你的REST风格的web服务在适当的时候返回gzip编码的内容。 所有的解码将在封面下完成。