Преобразование NSData в base64 - PullRequest
38 голосов
/ 04 февраля 2010

Как конвертировать NSData в base64. У меня есть NSData и я хочу преобразовать в base64 как я могу это сделать?

Ответы [ 7 ]

50 голосов
/ 04 февраля 2010

EDIT

Начиная с OS X 10.9 / iOS 7, это встроено в фреймворки.

См. -[NSData base64EncodedDataWithOptions:]


До iOS7 / OS X 10.9:

Мэтт Галлахер написал статью на эту самую тему. Внизу он дает ссылку на свой встраиваемый код для iPhone.

На Mac вы можете использовать библиотеку OpenSSL, на iPhone он пишет свой собственный impl.

27 голосов
/ 02 марта 2012
//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];
}
20 голосов
/ 21 сентября 2013

В качестве обновления iOS7 SDK имеет категорию на NSData (NSDataBase64Encoding) с методами

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

Следует избегать бросать свой метод категории

6 голосов
/ 08 апреля 2011

Супер-простой код библиотеки Google здесь.

Просто используйте +rfc4648Base64StringEncoding, чтобы получить экземпляр, затем используйте функции encode / decode.

Это прекрасная вещь. (Не забудьте взять файл заголовка и заголовок GTMDefines.h из корня.)

4 голосов
/ 04 февраля 2010

Это не легко.Как и в нет встроенной поддержки этого в c или obj-c.Вот что я делаю (что, в основном, делает CL для меня):

- (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;
}

И вы используете это так:

NSString *b64str = [strToConvert _base64Encoding:strToConvert];

И это не мой код -Я нашел это здесь: http://www.cocoadev.com/index.pl?BaseSixtyFour, и это прекрасно работает.Вы всегда можете превратить это в метод + ().

О, и получить ваши NSData для строки NSString для этого метода:

NSString *str = [[NSString alloc] initWithData:data encoding:NSASCIIStringEncoding];
2 голосов
/ 04 ноября 2013

iOS всегда включала встроенную поддержку кодирования и декодирования base64. Если вы посмотрите на resolv.h, вы увидите две функции b64_ntop и b64_pton. Библиотека Square SocketRocket предоставляет разумный пример использования этих функций из target-c.

Эти функции довольно хорошо протестированы и надежны - в отличие от многих реализаций, которые вы можете найти в случайных публикациях в Интернете. Не забудьте сделать ссылку на libresolv.dylib.

Если вы связываете с iOS 7 SDK, вы можете использовать более новые методы initWithBase64Encoding: и base64EncodedDataWithOptions:. Они существуют в предыдущих выпусках, но были частными. Так что если вы ссылаетесь на 6 SDK, вы можете столкнуться с неопределенным поведением. Это пример того, как использовать это только при связывании с 7 SDK:

#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
0 голосов
/ 17 мая 2013

Я изменил приведенный выше код в соответствии со своими потребностями, построив HTTP POST. Мне удалось пропустить шаг NSString и включить разрывы строк в код BASE64, который по крайней мере один веб-сервер нашел более приемлемым:

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