Преобразование NSData в base64

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

Ответ 1

ИЗМЕНИТЬ

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

См. -[NSData base64EncodedDataWithOptions:]


До iOS7/OS X 10.9:

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

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

Ответ 2

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

Ответ 3

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

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

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

Ответ 4

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

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

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

Ответ 5

Это нелегко. Как там, нет встроенной поддержки для этого в 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];

Ответ 6

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

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

Если вы связываетесь с iOS 7 SDK, вы можете использовать более новые методы initWithBase64Encoding: и base64EncodedDataWithOptions:. Они существуют в предыдущих выпусках, но являются частными. Поэтому, если вы ссылаетесь на 6 SDK, вы можете столкнуться с поведением undefined. Это будет пример использования этого только при связывании с 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

Ответ 7

Я изменил код выше, чтобы удовлетворить мои потребности, создав 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;
}