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 ?
Réponses
Trop de publicités?Il s’agit d’une affaire de bon usage pour Objective C catégories.
Pour le codage Base64 :
Pour le décodage de Base64 :
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;
}
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];
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
.