Converting NSData to base64
Как конвертировать NSData
в base64
, я имею NSData
and want to convert into base64
как я могу это сделать?
7 ответов
РЕДАКТИРОВАТЬ
Начиная с OS X 10.9 / iOS 7, это встроено в фреймворки.
Увидеть -[NSData base64EncodedDataWithOptions:]
До iOS7/OS X 10.9:
Мэтт Галлахер написал статью на эту тему. Внизу он дает ссылку на свой встраиваемый код для iPhone.
На Mac вы можете использовать библиотеку OpenSSL, на iPhone он пишет свой собственный impl.
//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];
}
В качестве обновления iOS7 SDK имеет категорию на NSData (NSDataBase64Encoding)
с методами
-[NSData base64EncodedStringWithOptions:]
-[NSData initWithBase64EncodedString:options:]
-[NSData initWithBase64EncodedData:options:]
-[NSData base64EncodedDataWithOptions:]
Следует избегать бросать свой собственный метод категории
Супер легко вставить код библиотеки Google здесь.
Просто используйте +rfc4648Base64StringEncoding
чтобы получить экземпляр, затем используйте encode
/decode
функции.
Это прекрасная вещь. (Не забудьте взять заголовочный файл и GTMDefines.h
заголовок от корня, правда.)
Это не просто. Как и в нет встроенной поддержки этого в 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];
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
Я изменил приведенный выше код в соответствии со своими потребностями, построив 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;
}