235 votes

Comment faire le codage base64 sur iphone-sdk ?

Je voudrais faire le décodage et l’encodage base64, mais je ne pouvais pas trouver n’importe quel support de l’iPhone SDK. Comment puis-je faire base64 encoder et décoder avec ou sans une bibliothèque ?

116voto

Alex Reynolds Points 45039

Il s’agit d’une affaire de bon usage pour Objective C catégories.

Pour le codage Base64 :

Pour le décodage de Base64 :

100voto

Mike Ho Points 971

Un très, très vite la mise en œuvre qui a été porté (et modifié/amélioré) à partir du PHP de Base de la bibliothèque en natif (Objective-C code est disponible dans le QSStrings Classe de la QSUtilities de la Bibliothèque. J'ai fait une rapide référence: 5.3 MB image (JPEG) fichier pris < 50ms à coder, et sur 140ms à décoder.

Le code pour l'ensemble de la bibliothèque (y compris le Base64 Méthodes) sont disponibles sur GitHub.

Ou sinon, si vous voulez le code pour juste le Base64 méthodes elles-mêmes, j'ai posté ici:

Tout d'abord, vous avez besoin de les tables de correspondance:

static const char _base64EncodingTable[64] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
static const short _base64DecodingTable[256] = {
    -2, -2, -2, -2, -2, -2, -2, -2, -2, -1, -1, -2, -1, -1, -2, -2,
    -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2,
    -1, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, 62, -2, -2, -2, 63,
    52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -2, -2, -2, -2, -2, -2,
    -2,  0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14,
    15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -2, -2, -2, -2, -2,
    -2, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
    41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -2, -2, -2, -2, -2,
    -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2,
    -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2,
    -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2,
    -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2,
    -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2,
    -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2,
    -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2,
    -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2
};

Pour Encoder:

+ (NSString *)encodeBase64WithString:(NSString *)strData {
    return [QSStrings encodeBase64WithData:[strData dataUsingEncoding:NSUTF8StringEncoding]];
}

+ (NSString *)encodeBase64WithData:(NSData *)objData {
    const unsigned char * objRawData = [objData bytes];
    char * objPointer;
    char * strResult;

    // Get the Raw Data length and ensure we actually have data
    int intLength = [objData length];
    if (intLength == 0) return nil;

    // Setup the String-based Result placeholder and pointer within that placeholder
    strResult = (char *)calloc((((intLength + 2) / 3) * 4) + 1, sizeof(char));
    objPointer = strResult;

    // Iterate through everything
    while (intLength > 2) { // keep going until we have less than 24 bits
        *objPointer++ = _base64EncodingTable[objRawData[0] >> 2];
        *objPointer++ = _base64EncodingTable[((objRawData[0] & 0x03) << 4) + (objRawData[1] >> 4)];
        *objPointer++ = _base64EncodingTable[((objRawData[1] & 0x0f) << 2) + (objRawData[2] >> 6)];
        *objPointer++ = _base64EncodingTable[objRawData[2] & 0x3f];

        // we just handled 3 octets (24 bits) of data
        objRawData += 3;
        intLength -= 3; 
    }

    // now deal with the tail end of things
    if (intLength != 0) {
        *objPointer++ = _base64EncodingTable[objRawData[0] >> 2];
        if (intLength > 1) {
            *objPointer++ = _base64EncodingTable[((objRawData[0] & 0x03) << 4) + (objRawData[1] >> 4)];
            *objPointer++ = _base64EncodingTable[(objRawData[1] & 0x0f) << 2];
            *objPointer++ = '=';
        } else {
            *objPointer++ = _base64EncodingTable[(objRawData[0] & 0x03) << 4];
            *objPointer++ = '=';
            *objPointer++ = '=';
        }
    }

    // Terminate the string-based result
    *objPointer = '\0';

    // Create result NSString object
    NSString *base64String = [NSString stringWithCString:strResult encoding:NSASCIIStringEncoding];

    // Free memory
    free(strResult);

    return base64String;
}

Pour Décoder:

+ (NSData *)decodeBase64WithString:(NSString *)strBase64 {
    const char *objPointer = [strBase64 cStringUsingEncoding:NSASCIIStringEncoding];
    size_t intLength = strlen(objPointer);
    int intCurrent;
    int i = 0, j = 0, k;

    unsigned char *objResult = calloc(intLength, sizeof(unsigned char));

    // Run through the whole string, converting as we go
    while ( ((intCurrent = *objPointer++) != '\0') && (intLength-- > 0) ) {
        if (intCurrent == '=') {
            if (*objPointer != '=' && ((i % 4) == 1)) {// || (intLength > 0)) {
                // the padding character is invalid at this point -- so this entire string is invalid
                free(objResult);
                return nil;
            }
            continue;
        }

        intCurrent = _base64DecodingTable[intCurrent];
        if (intCurrent == -1) {
            // we're at a whitespace -- simply skip over
            continue;
        } else if (intCurrent == -2) {
            // we're at an invalid character
            free(objResult);
            return nil;
        }

        switch (i % 4) {
            case 0:
                objResult[j] = intCurrent << 2;
                break;

            case 1:
                objResult[j++] |= intCurrent >> 4;
                objResult[j] = (intCurrent & 0x0f) << 4;
                break;

            case 2:
                objResult[j++] |= intCurrent >>2;
                objResult[j] = (intCurrent & 0x03) << 6;
                break;

            case 3:
                objResult[j++] |= intCurrent;
                break;
        }
        i++;
    }

    // mop things up if we ended on a boundary
    k = j;
    if (intCurrent == '=') {
        switch (i % 4) {
            case 1:
                // Invalid state
                free(objResult);
                return nil;

            case 2:
                k++;
                // flow through
            case 3:
                objResult[k] = 0;
        }
    }

    // Cleanup and setup the return NSData
    NSData * objData = [[[NSData alloc] initWithBytes:objResult length:j] autorelease];
    free(objResult);
    return objData;
}

78voto

Rob Points 70987

Historiquement, nous aurait dirigé vous vers l'un des nombreux tiers de la base de 64 bibliothèques (comme indiqué dans les autres réponses) pour la conversion de données binaires à base 64 de la chaîne (et de retour), mais iOS 7 a maintenant natif de codage en base 64 (et expose précédemment privé iOS 4 méthodes, dans le cas où vous avez besoin de support des versions antérieures d'iOS).

Ainsi, pour convertir NSData de NSString de la base de 64 représentation vous pouvez utiliser base64EncodedStringWithOptions. Si vous avez pour soutenir iOS versions antérieures à la version 7.0, vous pouvez le faire:

NSString *string;

if ([data respondsToSelector:@selector(base64EncodedStringWithOptions:)]) {
    string = [data base64EncodedStringWithOptions:kNilOptions];  // iOS 7+
} else {
    string = [data base64Encoding];                              // pre iOS7
}

Et à convertir en base 64 NSString de retour à l' NSData vous pouvez utiliser initWithBase64EncodedString. De même, si vous avez besoin de soutien iOS versions antérieures à la version 7.0, vous pouvez le faire:

NSData *data;

if ([NSData instancesRespondToSelector:@selector(initWithBase64EncodedString:options:)]) {
    data = [[NSData alloc] initWithBase64EncodedString:string options:kNilOptions];  // iOS 7+
} else {
    data = [[NSData alloc] initWithBase64Encoding:string];                           // pre iOS7
}

Évidemment, si vous n'avez pas besoin de compatibilité descendante avec les versions d'iOS antérieures à la version 7.0, il est encore plus facile, il suffit d'utiliser base64EncodedStringWithOptions ou initWithBase64EncodedString, respectivement, et ne vous embêtez pas avec le moment de l'exécution de vérifier pour d'anciennes versions iOS. En fait, si vous utilisez le code ci-dessus lorsque votre objectif minimum est de iOS 7 ou plus, vous recevrez un avertissement du compilateur sur les méthodes obsolètes. Donc, dans iOS 7 et plus, il vous suffit de convertir en base 64 chaîne avec:

NSString *string = [data base64EncodedStringWithOptions:kNilOptions];

et de retour à nouveau avec:

NSData *data = [[NSData alloc] initWithBase64EncodedString:string options:kNilOptions]; 

73voto

Greg Bernhardt Points 3453

Il y a un échantillon de code de nice au bas de ce post. Très autonome...

BaseSixtyFour

33voto

quellish Points 5475

iOS comprend un support intégré pour les base64 d'encodage et de décodage. Si vous regardez resolv.h vous devriez voir les deux fonctions b64_ntop et b64_pton . La Place SocketRocket bibliothèque génère un exemple d'utilisation de ces fonctions à partir d'objective-c.

Ces fonctions sont assez bien testé et fiable - à la différence de la plupart des implémentations vous pouvez trouver aléatoire des messages envoyés sur internet. N'oubliez pas de lien à l'encontre libresolv.dylib.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X