Domanda

È disponibile un'API di compressione da utilizzare su iPhone? Stiamo costruendo alcuni servizi Web RESTful per la nostra app per iPhone con cui parlare, ma vogliamo comprimere almeno alcune delle conversazioni per efficienza.

Non mi interessa quale sia il formato (ZIP, LHA, qualunque sia) e non deve essere sicuro.

Alcuni intervistati hanno sottolineato che il server può comprimere il suo output e l'iPhone può consumarlo. Lo scenario che abbiamo è esattamente il contrario. Pubblicheremo il contenuto compresso da a il servizio web. Non ci preoccupiamo che la compressione vada dall'altra parte.

È stato utile?

Soluzione

zlib e bzip2 sono disponibili. E puoi sempre aggiungerne altri, purché (generalmente) vengano compilati sotto OS X.

bzip2 è una scelta migliore per file di dimensioni ridotte, ma richiede molta più potenza della CPU per comprimere e decomprimere.

Inoltre, poiché stai parlando con un servizio web, potresti non dover fare molto. NSURLRequest accetta la codifica gzip in modo trasparente nelle risposte del server.

Altri suggerimenti

Se memorizzi i dati per le conversazioni in un oggetto NSData, le persone del wiki CocoaDev hanno pubblicato un Categoria NSData che aggiunge la compressione / decompressione di gzip e zlib come metodi semplici. Questi hanno funzionato bene per me in la mia applicazione per iPhone .

Dato che il link sopra è morto mentre il wiki di CocoaDev viene spostato su un nuovo host, ho riprodotto questa categoria nella sua interezza di seguito.

Interfaccia:

@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

Implementazione:

#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

La libcompression integrata di Apple è ora disponibile per iOS 9. Di seguito è mostrato un breve esempio di compressione_encode_buffer per la compressione di 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);

Sono disponibili diversi algoritmi:

  • LZMA
  • LZ4
  • ZLIB
  • LZFSE

Sono supportati sia la compressione a blocchi che la compressione di flusso.

Vedi https://developer.apple.com/library/ mac / documentazione / performance / Reference / compressione /

Se hai solo dati compressi e conosci dimensioni non compresse puoi usare:

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

Credo che zlib è disponibile al telefono.

fidati di me la scelta migliore è usare ZipArchive vedi: Come fare decomprimere un file zip crittografato AES-256?

pronto per l'aiuto, se necessario.

Objective-Zip è un'altra opzione. Guarda queste eccellenti istruzioni .

Nota che ho dovuto convertire il codice sorgente per usare ARC usando XCode- > Edit- > Refactor- > Converti in Objective C ARC.

NSURL afferma che supporta la codifica gzip, quindi non dovresti fare altro che fare in modo che il tuo servizio web RESTful restituisca contenuti codificati gzip quando appropriato. Tutta la decodifica verrà eseguita sotto le copertine.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top