web-dev-qa-db-fra.com

Conversion de NSData en base64

Comment convertir NSData en base64. J'ai NSData et je souhaite convertir en base64 Comment puis-je faire ceci?

38
mactalent

[~ # ~] modifier [~ # ~]

Depuis OS X 10.9/iOS 7, cela est intégré dans les frameworks.

Voir -[NSData base64EncodedDataWithOptions:]


Avant iOS7/OS X 10.9:

Matt Gallagher a écrit n article sur ce même sujet. En bas, il donne un lien vers son code intégrable pour iPhone.

Sur le mac, vous pouvez utiliser la bibliothèque OpenSSL, sur l'iPhone, il écrit son propre impl.

50
Ken
//from: http://cocoadev.com/BaseSixtyFour
+ (NSString*)base64forData:(NSData*)theData {

    const uint8_t* input = (const uint8_t*)[theData bytes];
    NSInteger length = [theData length];

  static char table[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";

  NSMutableData* data = [NSMutableData dataWithLength:((length + 2) / 3) * 4];
  uint8_t* output = (uint8_t*)data.mutableBytes;

    NSInteger i;
  for (i=0; i < length; i += 3) {
    NSInteger value = 0;
        NSInteger j;
    for (j = i; j < (i + 3); j++) {
      value <<= 8;

      if (j < length) {
        value |= (0xFF & input[j]);
      }
    }

    NSInteger theIndex = (i / 3) * 4;
    output[theIndex + 0] =                    table[(value >> 18) & 0x3F];
    output[theIndex + 1] =                    table[(value >> 12) & 0x3F];
    output[theIndex + 2] = (i + 1) < length ? table[(value >> 6)  & 0x3F] : '=';
    output[theIndex + 3] = (i + 2) < length ? table[(value >> 0)  & 0x3F] : '=';
  }

  return [[[NSString alloc] initWithData:data encoding:NSASCIIStringEncoding] autorelease];
}
27
joshrl

En tant que mise à jour, le SDK iOS7 a une catégorie sur NSData (NSDataBase64Encoding) avec des méthodes

-[NSData base64EncodedStringWithOptions:]
-[NSData initWithBase64EncodedString:options:]
-[NSData initWithBase64EncodedData:options:]
-[NSData base64EncodedDataWithOptions:]

Devrait éviter d'avoir à lancer votre propre méthode de catégorie

20
Damien Pontifex

Code de bibliothèque Google super facile à insérer ici.

Utilisez simplement +rfc4648Base64StringEncoding pour obtenir une instance, puis utilisez les fonctions encode/decode.

C'est une belle chose. (N'oubliez pas de récupérer le fichier d'en-tête et le GTMDefines.h en-tête de la racine, cependant.)

6
Ben Mosher

Ce n'est pas facile. Comme dans il n'y a pas de support intégré pour cela dans c ou obj-c. Voici ce que je fais (ce qui fait que le CL le fait pour moi):

- (NSString *)_base64Encoding:(NSString *) str
{
    NSTask *task = [[[NSTask alloc] init] autorelease];
    NSPipe *inPipe = [NSPipe pipe], *outPipe = [NSPipe pipe];
    NSFileHandle *inHandle = [inPipe fileHandleForWriting], *outHandle = [outPipe fileHandleForReading];
    NSData *outData = nil;

    [task setLaunchPath:@"/usr/bin/openssl"];
    [task setArguments:[NSArray arrayWithObjects:@"base64", @"-e", nil]];
    [task setStandardInput:inPipe];
    [task setStandardOutput:outPipe];
    [task setStandardError:outPipe];

    [task launch];

    [inHandle writeData:[str dataUsingEncoding: NSASCIIStringEncoding]];
    [inHandle closeFile];

    [task waitUntilExit];

    outData = [outHandle readDataToEndOfFile];
    if (outData)
    {
        NSString *base64 = [[[NSString alloc] initWithData:outData encoding:NSUTF8StringEncoding] autorelease];
        if (base64)
            return base64;
    }

    return nil;
}

Et vous l'utilisez comme ceci:

NSString *b64str = [strToConvert _base64Encoding:strToConvert];

Et ce n'est pas mon code - je l'ai trouvé ici: http://www.cocoadev.com/index.pl?BaseSixtyFour et cela fonctionne très bien. Vous pouvez toujours transformer cela en une méthode + ().

Oh, et pour obtenir votre NSData sur une NSString pour cette méthode:

NSString *str = [[NSString alloc] initWithData:data encoding:NSASCIIStringEncoding];
4
mr-sk

iOS a toujours inclus une prise en charge intégrée pour l'encodage et le décodage base64. Si vous regardez resolv.h vous devriez voir les deux fonctions b64_ntop et b64_pton. La bibliothèque Square SocketRocket fournit un exemple raisonnable de la façon d'utiliser ces fonctions depuis objective-c.

Ces fonctions sont assez bien testées et fiables - contrairement à la plupart des implémentations que vous pouvez trouver dans des publications Internet aléatoires. N'oubliez pas de lier contre libresolv.dylib.

Si vous liez au SDK iOS 7, vous pouvez utiliser les nouvelles méthodes initWithBase64Encoding: et base64EncodedDataWithOptions:. Ceux-ci existent dans les versions précédentes, mais étaient privés. Donc, si vous établissez un lien avec le SDK 6, vous pouvez rencontrer un comportement non défini. Ce serait un exemple de la façon de l'utiliser uniquement lors de la liaison avec le SDK 7:

#ifndef __IPHONE_7_0
    // oh no! you are using something unsupported!
    // Call and implementation that uses b64_pton here
#else
    data = [[NSData alloc] initWithBase64Encoding:string];
#endif
2
quellish

J'ai modifié le code ci-dessus pour répondre à mes besoins, en créant un HTTP POST. J'ai pu ignorer l'étape NSString et inclure des sauts de ligne dans le code BASE64, qui au moins un serveur Web a trouvé plus acceptable:

#define LINE_SIZE   76

//originally from: http://www.cocoadev.com/index.pl?BaseSixtyFour
// via joshrl on stockoverflow

- (void) appendBase64Of: (NSData *)inData to:(NSMutableData *)outData {
    const uint8_t* input = (const uint8_t*)[inData bytes];
    NSInteger length = [inData length];

    static char table[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";

    uint8_t buf[LINE_SIZE + 4 + 2];
    size_t n = 0;

    NSInteger i;
    for (i=0; i < length; i += 3) {
        NSInteger value = 0;
        NSInteger j;
        for (j = i; j < (i + 3); j++) {
            value <<= 8;

            if (j < length) {
                value |= (0xFF & input[j]);
            }
        }

        buf[n + 0] =                    table[(value >> 18) & 0x3F];
        buf[n + 1] =                    table[(value >> 12) & 0x3F];
        buf[n + 2] = (i + 1) < length ? table[(value >> 6)  & 0x3F] : '=';
        buf[n + 3] = (i + 2) < length ? table[(value >> 0)  & 0x3F] : '=';
        n += 4;
        if (n + 2 >= LINE_SIZE) {
            buf[n++] = '\r';
            buf[n++] = '\n';
            [outData appendBytes:buf length:n];
            n = 0;
        }
    }
    if (n > 0) {
        buf[n++] = '\r';
        buf[n++] = '\n';
        [outData appendBytes:buf length:n];
    }
    return;
}
0
Bill Cheswick