Как мне сделать кодировку Base64 на iPhone?
Я нашел несколько примеров, которые выглядели многообещающими, но никогда не могли заставить их работать над телефоном.
Как мне сделать кодировку Base64 на iPhone?
Я нашел несколько примеров, которые выглядели многообещающими, но никогда не могли заставить их работать над телефоном.
Здесь вы можете увидеть пример .
Это для iOS7 +.
Я копирую код здесь, на всякий случай:
// Create NSData object
NSData *nsdata = [@"iOS Developer Tips encoded in Base64"
dataUsingEncoding:NSUTF8StringEncoding];
// Get NSString from NSData object in Base64
NSString *base64Encoded = [nsdata base64EncodedStringWithOptions:0];
// Print the Base64 encoded string
NSLog(@"Encoded: %@", base64Encoded);
// Let go the other way...
// NSData from the Base64 encoded str
NSData *nsdataFromBase64String = [[NSData alloc]
initWithBase64EncodedString:base64Encoded options:0];
// Decoded NSString from the NSData
NSString *base64Decoded = [[NSString alloc]
initWithData:nsdataFromBase64String encoding:NSUTF8StringEncoding];
NSLog(@"Decoded: %@", base64Decoded);
Мне также не удалось найти рабочий код для iPhone, который я мог понять.
Я, наконец, написал это.
-(NSString *)Base64Encode:(NSData *)data;
-(NSString *)Base64Encode:(NSData *)data{
//Point to start of the data and set buffer sizes
int inLength = [data length];
int outLength = ((((inLength * 4)/3)/4)*4) + (((inLength * 4)/3)%4 ? 4 : 0);
const char *inputBuffer = [data bytes];
char *outputBuffer = malloc(outLength+1);
outputBuffer[outLength] = 0;
//64 digit code
static char Encode[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
//Start the count
int cycle = 0;
int inpos = 0;
int outpos = 0;
char temp;
//Pad the last to bytes, the outbuffer must always be a multiple of 4.
outputBuffer[outLength-1] = '=';
outputBuffer[outLength-2] = '=';
/* http://en.wikipedia.org/wiki/Base64
Text content M a n
ASCII 77 97 110
8 Bit pattern 01001101 01100001 01101110
6 Bit pattern 010011 010110 000101 101110
Index 19 22 5 46
Base64-encoded T W F u
*/
while (inpos < inLength){
switch (cycle) {
case 0:
outputBuffer[outpos++] = Encode[(inputBuffer[inpos] & 0xFC) >> 2];
cycle = 1;
break;
case 1:
temp = (inputBuffer[inpos++] & 0x03) << 4;
outputBuffer[outpos] = Encode[temp];
cycle = 2;
break;
case 2:
outputBuffer[outpos++] = Encode[temp|(inputBuffer[inpos]&0xF0) >> 4];
temp = (inputBuffer[inpos++] & 0x0F) << 2;
outputBuffer[outpos] = Encode[temp];
cycle = 3;
break;
case 3:
outputBuffer[outpos++] = Encode[temp|(inputBuffer[inpos]&0xC0) >> 6];
cycle = 4;
break;
case 4:
outputBuffer[outpos++] = Encode[inputBuffer[inpos++] & 0x3f];
cycle = 0;
break;
default:
cycle = 0;
break;
}
}
NSString *pictemp = [NSString stringWithUTF8String:outputBuffer];
free(outputBuffer);
return pictemp;
}
Используйте эту библиотеку для кодирования Base64.
Он также поддерживает ARC
Попробуйте это... это отлично сработало для меня. Создайте категорию Base64.h и Base 64.m, Импортируйте в любой класс, который хотите использовать, и вызовите его с использованием одной строки для кодирования base 64.
//
// Base64.h
// CryptTest
// Created by SURAJ K THOMAS on 02/05/2013.
#import <Foundation/Foundation.h>
@interface Base64 : NSObject {
}
+ (void) initialize;
+ (NSString*) encode:(const uint8_t*) input length:(NSInteger) length;
+ (NSString*) encode:(NSData*) rawBytes;
+ (NSData*) decode:(const char*) string length:(NSInteger) inputLength;
+ (NSData*) decode:(NSString*) string;
@end
#import "Base64.h"
@implementation Base64
#define ArrayLength(x) (sizeof(x)/sizeof(*(x)))
static char encodingTable[] =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
static char decodingTable[128];
+ (void) initialize {
if (self == [Base64 class]) {
memset(decodingTable, 0, ArrayLength(decodingTable));
for (NSInteger i = 0; i < ArrayLength(encodingTable); i++) {
decodingTable[encodingTable[i]] = i;
}
}
}
+ (NSString*) encode:(const uint8_t*) input length:(NSInteger) length {
NSMutableData* data = [NSMutableData dataWithLength:((length + 2) / 3) * 4];
uint8_t* output = (uint8_t*)data.mutableBytes;
for (NSInteger i = 0; i < length; i += 3) {
NSInteger value = 0;
for (NSInteger j = i; j < (i + 3); j++) {
value <<= 8;
if (j < length) {
value |= (0xFF & input[j]);
}
}
NSInteger index = (i / 3) * 4;
output[index + 0] = encodingTable[(value >> 18) & 0x3F];
output[index + 1] = encodingTable[(value >> 12) & 0x3F];
output[index + 2] = (i + 1) < length ? encodingTable[(value >> 6) & 0x3F] : '=';
output[index + 3] = (i + 2) < length ? encodingTable[(value >> 0) & 0x3F] : '=';
}
return [[NSString alloc] initWithData:data
encoding:NSASCIIStringEncoding];
}
+ (NSString*) encode:(NSData*) rawBytes {
return [self encode:(const uint8_t*) rawBytes.bytes length:rawBytes.length];
}
+ (NSData*) decode:(const char*) string length:(NSInteger) inputLength {
if ((string == NULL) || (inputLength % 4 != 0)) {
return nil;
}
while (inputLength > 0 && string[inputLength - 1] == '=') {
inputLength--;
}
NSInteger outputLength = inputLength * 3 / 4;
NSMutableData* data = [NSMutableData dataWithLength:outputLength];
uint8_t* output = data.mutableBytes;
NSInteger inputPoint = 0;
NSInteger outputPoint = 0;
while (inputPoint < inputLength) {
char i0 = string[inputPoint++];
char i1 = string[inputPoint++];
char i2 = inputPoint < inputLength ? string[inputPoint++] : 'A'; /* 'A' will
decode to \0 */
char i3 = inputPoint < inputLength ? string[inputPoint++] : 'A';
output[outputPoint++] = (decodingTable[i0] << 2) | (decodingTable[i1] >> 4);
if (outputPoint < outputLength) {
output[outputPoint++] = ((decodingTable[i1] & 0xf) << 4) |
(decodingTable[i2] >> 2);
}
if (outputPoint < outputLength) {
output[outputPoint++] = ((decodingTable[i2] & 0x3) << 6) |
decodingTable[i3];
}
}
return data;
}
+ (NSData*) decode:(NSString*) string {
return [self decode:[string cStringUsingEncoding:NSASCIIStringEncoding]
length:string.length];
}
@end
now import the above category to any class and convert the string like below
NSString *authString = [[NSString stringWithFormat:@"OD0EK819OJFIFT6OJZZXT09Y1YUT1EJ2"]
stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
NSData *inputData = [authString dataUsingEncoding:NSUTF8StringEncoding];
NSString *finalAuth =[Base64 encode:inputData];
NSLog(@"Encoded string =%@", finalAuth);
Загрузите два файла из GitHub
Base64.h
Base64.m
Добавьте эти файлы в свой проект
Импортировать файл заголовка в желаемый файл
#import "Base64.h"
И использовать для кодирования
NSString *plainText = @"Your String";
NSString *base64String = [plainText base64EncodedStringWithWrapWidth:0];
Также вы можете декодировать его как
NSString *plainText = [base64String base64DecodedString];
Кажется, что с iOS 7 вам больше не нужны библиотеки для кодирования в Base64. Следующие методы NSData могут использоваться для кодирования Base64:
NSString *plainString = @"foo";
Кодировка
NSData *plainData = [plainString dataUsingEncoding:NSUTF8StringEncoding];
NSString *base64String = [plainData base64EncodedStringWithOptions:0];
NSLog(@"%@", base64String); // Zm9v
Декодирование
NSData *decodedData = [[NSData alloc] initWithBase64EncodedString:base64String options:0];
NSString *decodedString = [[NSString alloc] initWithData:decodedData encoding:NSUTF8StringEncoding];
NSLog(@"%@", decodedString); // foo
Метод в категории NSData
- (NSString*)encodeBase64 {
static char* alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
unsigned int length = self.length;
unsigned const char* rawData = self.bytes;
//empty data = empty output
if (length == 0) {
return @"";
}
unsigned int outputLength = (((length + 2) / 3) * 4);
//let allocate buffer for the output
char* rawOutput = malloc(outputLength + 1);
//with each step we get 3 bytes from the input and write 4 bytes to the output
for (unsigned int i = 0, outputIndex = 0; i < length; i += 3, outputIndex += 4) {
BOOL triple = NO;
BOOL quad = NO;
//get 3 bytes (or only 1 or 2 when we have reached the end of input)
unsigned int value = rawData[i];
value <<= 8;
if (i + 1 < length) {
value |= rawData[i + 1];
triple = YES;
}
value <<= 8;
if (i + 2 < length) {
value |= rawData[i + 2];
quad = YES;
}
//3 * 8 bits written as 4 * 6 bits (indexing the 64 chars of the alphabet)
//write = if end of input reached
rawOutput[outputIndex + 3] = (quad) ? alphabet[value & 0x3F] : '=';
value >>= 6;
rawOutput[outputIndex + 2] = (triple) ? alphabet[value & 0x3F] : '=';
value >>= 6;
rawOutput[outputIndex + 1] = alphabet[value & 0x3F];
value >>= 6;
rawOutput[outputIndex] = alphabet[value & 0x3F];
}
rawOutput[outputLength] = 0;
NSString* output = [NSString stringWithCString:rawOutput encoding:NSASCIIStringEncoding];
free(rawOutput);
return output;
}
Я выполнил свою собственную реализацию, где были удалены все проверки внутри цикла. Таким образом, на большом количестве данных он работает быстрее. Вы можете принять это за основу для собственного решения.
static char *alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+ (NSString *)encodeString:(NSString *)data
{
const char *input = [data cStringUsingEncoding:NSUTF8StringEncoding];
unsigned long inputLength = [data length];
unsigned long modulo = inputLength % 3;
unsigned long outputLength = (inputLength / 3) * 4 + (modulo ? 4 : 0);
unsigned long j = 0;
// Do not forget about trailing zero
unsigned char *output = malloc(outputLength + 1);
output[outputLength] = 0;
// Here are no checks inside the loop, so it works much faster than other implementations
for (unsigned long i = 0; i < inputLength; i += 3) {
output[j++] = alphabet[ (input[i] & 0xFC) >> 2 ];
output[j++] = alphabet[ ((input[i] & 0x03) << 4) | ((input[i + 1] & 0xF0) >> 4) ];
output[j++] = alphabet[ ((input[i + 1] & 0x0F)) << 2 | ((input[i + 2] & 0xC0) >> 6) ];
output[j++] = alphabet[ (input[i + 2] & 0x3F) ];
}
// Padding in the end of encoded string directly depends of modulo
if (modulo > 0) {
output[outputLength - 1] = '=';
if (modulo == 1)
output[outputLength - 2] = '=';
}
NSString *s = [NSString stringWithUTF8String:(const char *)output];
free(output);
return s;
}