ฉันต้องการที่จะทำbase64
การเข้ารหัสและถอดรหัส แต่ฉันไม่สามารถหาการสนับสนุนใด ๆ จาก SDK
iPhone ฉันจะbase64
เข้ารหัสและถอดรหัสโดยมีหรือไม่มีห้องสมุดได้อย่างไร
ฉันต้องการที่จะทำbase64
การเข้ารหัสและถอดรหัส แต่ฉันไม่สามารถหาการสนับสนุนใด ๆ จาก SDK
iPhone ฉันจะbase64
เข้ารหัสและถอดรหัสโดยมีหรือไม่มีห้องสมุดได้อย่างไร
คำตอบ:
นี่คือกรณีการใช้งานที่ดีสำหรับวัตถุประสงค์ C ประเภท
สำหรับการเข้ารหัส Base64:
#import <Foundation/NSString.h>
@interface NSString (NSStringAdditions)
+ (NSString *) base64StringFromData:(NSData *)data length:(int)length;
@end
-------------------------------------------
#import "NSStringAdditions.h"
static char base64EncodingTable[64] = {
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f',
'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/'
};
@implementation NSString (NSStringAdditions)
+ (NSString *) base64StringFromData: (NSData *)data length: (int)length {
unsigned long ixtext, lentext;
long ctremaining;
unsigned char input[3], output[4];
short i, charsonline = 0, ctcopy;
const unsigned char *raw;
NSMutableString *result;
lentext = [data length];
if (lentext < 1)
return @"";
result = [NSMutableString stringWithCapacity: lentext];
raw = [data bytes];
ixtext = 0;
while (true) {
ctremaining = lentext - ixtext;
if (ctremaining <= 0)
break;
for (i = 0; i < 3; i++) {
unsigned long ix = ixtext + i;
if (ix < lentext)
input[i] = raw[ix];
else
input[i] = 0;
}
output[0] = (input[0] & 0xFC) >> 2;
output[1] = ((input[0] & 0x03) << 4) | ((input[1] & 0xF0) >> 4);
output[2] = ((input[1] & 0x0F) << 2) | ((input[2] & 0xC0) >> 6);
output[3] = input[2] & 0x3F;
ctcopy = 4;
switch (ctremaining) {
case 1:
ctcopy = 2;
break;
case 2:
ctcopy = 3;
break;
}
for (i = 0; i < ctcopy; i++)
[result appendString: [NSString stringWithFormat: @"%c", base64EncodingTable[output[i]]]];
for (i = ctcopy; i < 4; i++)
[result appendString: @"="];
ixtext += 3;
charsonline += 4;
if ((length > 0) && (charsonline >= length))
charsonline = 0;
}
return result;
}
@end
สำหรับการถอดรหัส Base64:
#import <Foundation/Foundation.h>
@class NSString;
@interface NSData (NSDataAdditions)
+ (NSData *) base64DataFromString:(NSString *)string;
@end
-------------------------------------------
#import "NSDataAdditions.h"
@implementation NSData (NSDataAdditions)
+ (NSData *)base64DataFromString: (NSString *)string
{
unsigned long ixtext, lentext;
unsigned char ch, inbuf[4], outbuf[3];
short i, ixinbuf;
Boolean flignore, flendtext = false;
const unsigned char *tempcstring;
NSMutableData *theData;
if (string == nil)
{
return [NSData data];
}
ixtext = 0;
tempcstring = (const unsigned char *)[string UTF8String];
lentext = [string length];
theData = [NSMutableData dataWithCapacity: lentext];
ixinbuf = 0;
while (true)
{
if (ixtext >= lentext)
{
break;
}
ch = tempcstring [ixtext++];
flignore = false;
if ((ch >= 'A') && (ch <= 'Z'))
{
ch = ch - 'A';
}
else if ((ch >= 'a') && (ch <= 'z'))
{
ch = ch - 'a' + 26;
}
else if ((ch >= '0') && (ch <= '9'))
{
ch = ch - '0' + 52;
}
else if (ch == '+')
{
ch = 62;
}
else if (ch == '=')
{
flendtext = true;
}
else if (ch == '/')
{
ch = 63;
}
else
{
flignore = true;
}
if (!flignore)
{
short ctcharsinbuf = 3;
Boolean flbreak = false;
if (flendtext)
{
if (ixinbuf == 0)
{
break;
}
if ((ixinbuf == 1) || (ixinbuf == 2))
{
ctcharsinbuf = 1;
}
else
{
ctcharsinbuf = 2;
}
ixinbuf = 3;
flbreak = true;
}
inbuf [ixinbuf++] = ch;
if (ixinbuf == 4)
{
ixinbuf = 0;
outbuf[0] = (inbuf[0] << 2) | ((inbuf[1] & 0x30) >> 4);
outbuf[1] = ((inbuf[1] & 0x0F) << 4) | ((inbuf[2] & 0x3C) >> 2);
outbuf[2] = ((inbuf[2] & 0x03) << 6) | (inbuf[3] & 0x3F);
for (i = 0; i < ctcharsinbuf; i++)
{
[theData appendBytes: &outbuf[i] length: 1];
}
}
if (flbreak)
{
break;
}
}
}
return theData;
}
@end
การดำเนินจริงๆรวดเร็วจริงๆซึ่งเป็นลาง (และการแก้ไข / ปรับปรุง) จากห้องสมุด PHP หลักเป็นรหัส Objective-C พื้นเมืองที่มีอยู่ในระดับ QSStringsจากห้องสมุด QSUtilities ฉันทำเกณฑ์มาตรฐานอย่างรวดเร็ว: ไฟล์รูปภาพ (JPEG) 5.3MB ใช้เวลา <50ms ในการเข้ารหัสและประมาณ 140 มิลลิวินาทีในการถอดรหัส
รหัสสำหรับห้องสมุดทั้งหมด (รวมทั้งวิธีการ Base64) ที่มีอยู่บนGitHub
หรือมิฉะนั้นถ้าคุณต้องการให้รหัสเป็นเพียงวิธี Base64 เองฉันได้โพสต์ไว้ที่นี่:
ก่อนอื่นคุณต้องมีตารางการจับคู่:
static const char _base64EncodingTable[64] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
static const short _base64DecodingTable[256] = {
-2, -2, -2, -2, -2, -2, -2, -2, -2, -1, -1, -2, -1, -1, -2, -2,
-2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2,
-1, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, 62, -2, -2, -2, 63,
52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -2, -2, -2, -2, -2, -2,
-2, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -2, -2, -2, -2, -2,
-2, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -2, -2, -2, -2, -2,
-2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2,
-2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2,
-2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2,
-2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2,
-2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2,
-2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2,
-2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2,
-2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2
};
ในการเข้ารหัส:
+ (NSString *)encodeBase64WithString:(NSString *)strData {
return [QSStrings encodeBase64WithData:[strData dataUsingEncoding:NSUTF8StringEncoding]];
}
+ (NSString *)encodeBase64WithData:(NSData *)objData {
const unsigned char * objRawData = [objData bytes];
char * objPointer;
char * strResult;
// Get the Raw Data length and ensure we actually have data
int intLength = [objData length];
if (intLength == 0) return nil;
// Setup the String-based Result placeholder and pointer within that placeholder
strResult = (char *)calloc((((intLength + 2) / 3) * 4) + 1, sizeof(char));
objPointer = strResult;
// Iterate through everything
while (intLength > 2) { // keep going until we have less than 24 bits
*objPointer++ = _base64EncodingTable[objRawData[0] >> 2];
*objPointer++ = _base64EncodingTable[((objRawData[0] & 0x03) << 4) + (objRawData[1] >> 4)];
*objPointer++ = _base64EncodingTable[((objRawData[1] & 0x0f) << 2) + (objRawData[2] >> 6)];
*objPointer++ = _base64EncodingTable[objRawData[2] & 0x3f];
// we just handled 3 octets (24 bits) of data
objRawData += 3;
intLength -= 3;
}
// now deal with the tail end of things
if (intLength != 0) {
*objPointer++ = _base64EncodingTable[objRawData[0] >> 2];
if (intLength > 1) {
*objPointer++ = _base64EncodingTable[((objRawData[0] & 0x03) << 4) + (objRawData[1] >> 4)];
*objPointer++ = _base64EncodingTable[(objRawData[1] & 0x0f) << 2];
*objPointer++ = '=';
} else {
*objPointer++ = _base64EncodingTable[(objRawData[0] & 0x03) << 4];
*objPointer++ = '=';
*objPointer++ = '=';
}
}
// Terminate the string-based result
*objPointer = '\0';
// Create result NSString object
NSString *base64String = [NSString stringWithCString:strResult encoding:NSASCIIStringEncoding];
// Free memory
free(strResult);
return base64String;
}
เพื่อถอดรหัส:
+ (NSData *)decodeBase64WithString:(NSString *)strBase64 {
const char *objPointer = [strBase64 cStringUsingEncoding:NSASCIIStringEncoding];
size_t intLength = strlen(objPointer);
int intCurrent;
int i = 0, j = 0, k;
unsigned char *objResult = calloc(intLength, sizeof(unsigned char));
// Run through the whole string, converting as we go
while ( ((intCurrent = *objPointer++) != '\0') && (intLength-- > 0) ) {
if (intCurrent == '=') {
if (*objPointer != '=' && ((i % 4) == 1)) {// || (intLength > 0)) {
// the padding character is invalid at this point -- so this entire string is invalid
free(objResult);
return nil;
}
continue;
}
intCurrent = _base64DecodingTable[intCurrent];
if (intCurrent == -1) {
// we're at a whitespace -- simply skip over
continue;
} else if (intCurrent == -2) {
// we're at an invalid character
free(objResult);
return nil;
}
switch (i % 4) {
case 0:
objResult[j] = intCurrent << 2;
break;
case 1:
objResult[j++] |= intCurrent >> 4;
objResult[j] = (intCurrent & 0x0f) << 4;
break;
case 2:
objResult[j++] |= intCurrent >>2;
objResult[j] = (intCurrent & 0x03) << 6;
break;
case 3:
objResult[j++] |= intCurrent;
break;
}
i++;
}
// mop things up if we ended on a boundary
k = j;
if (intCurrent == '=') {
switch (i % 4) {
case 1:
// Invalid state
free(objResult);
return nil;
case 2:
k++;
// flow through
case 3:
objResult[k] = 0;
}
}
// Cleanup and setup the return NSData
NSData * objData = [[[NSData alloc] initWithBytes:objResult length:j] autorelease];
free(objResult);
return objData;
}
strResult
ในตัวเข้ารหัสดูเหมือนจะรั่วไหลออกมา มันต้องการเพียงแค่free()
ตอนจบ (ก่อนกลับมา แต่หลังจากNSString stringWithCString
)
encodeBase64WithData:
วิธีการของคุณพารามิเตอร์แรกในการเรียกจะcalloc()
ต้องเพิ่มขึ้น 1 เพื่อบัญชีสำหรับตัวสิ้นสุดของโมฆะ ( '\0'
) ที่คุณเพิ่มในตอนท้ายหรือไม่
ในอดีตเราจะได้กำกับให้คุณหนึ่งในหลายฐานของบุคคลที่สาม 64 ห้องสมุด (ตามที่กล่าวในคำตอบอื่น ๆ ) สำหรับการแปลงจากข้อมูลไบนารีไปยังฐาน 64 สตริง (และกลับ) แต่ iOS 7 ตอนนี้มีพื้นเมืองฐาน 64 เข้ารหัส (และ เปิดเผยวิธีการ iOS 4 ส่วนตัวก่อนหน้านี้ในกรณีที่คุณต้องการสนับสนุน iOS เวอร์ชันก่อนหน้า)
ดังนั้นการแปลงNSData
ไปยังNSString
ฐาน 64 base64EncodedStringWithOptions
เป็นตัวแทนคุณสามารถใช้ หากคุณต้องสนับสนุน iOS เวอร์ชัน 7.0 ก่อนเช่นกันคุณสามารถทำได้:
NSString *string;
if ([data respondsToSelector:@selector(base64EncodedStringWithOptions:)]) {
string = [data base64EncodedStringWithOptions:kNilOptions]; // iOS 7+
} else {
string = [data base64Encoding]; // pre iOS7
}
และไปยังฐานแปลง 64 NSString
กลับไปที่คุณสามารถใช้NSData
initWithBase64EncodedString
ในทำนองเดียวกันหากคุณต้องการสนับสนุน iOS เวอร์ชันก่อน 7.0 คุณสามารถทำได้:
NSData *data;
if ([NSData instancesRespondToSelector:@selector(initWithBase64EncodedString:options:)]) {
data = [[NSData alloc] initWithBase64EncodedString:string options:kNilOptions]; // iOS 7+
} else {
data = [[NSData alloc] initWithBase64Encoding:string]; // pre iOS7
}
เห็นได้ชัดว่าถ้าคุณไม่ต้องการความเข้ากันได้ย้อนหลังกับ iOS เวอร์ชันก่อน 7.0 มันง่ายยิ่งขึ้นเพียงใช้base64EncodedStringWithOptions
หรือinitWithBase64EncodedString
ตามลำดับและไม่ต้องกังวลกับการตรวจสอบรันไทม์สำหรับ iOS เวอร์ชันก่อนหน้า ในความเป็นจริงถ้าคุณใช้รหัสด้านบนเมื่อเป้าหมายขั้นต่ำของคุณคือ iOS 7 หรือสูงกว่าคุณจะได้รับคำเตือนของคอมไพเลอร์เกี่ยวกับวิธีการที่เลิกใช้แล้ว ดังนั้นใน iOS 7 ขึ้นไปคุณจะแปลงเป็นเบสสตริง 64 ด้วย:
NSString *string = [data base64EncodedStringWithOptions:kNilOptions];
และกลับมาอีกครั้งด้วย:
NSData *data = [[NSData alloc] initWithBase64EncodedString:string options:kNilOptions];
iOS รวมถึงการสนับสนุนการเข้ารหัสและถอดรหัส base64 ในตัว ถ้าคุณดูที่resolv.h
คุณควรจะเห็นทั้งสองฟังก์ชั่นและb64_ntop
ไลบรารีb64_pton
Square SocketRocketให้ตัวอย่างที่เหมาะสมของวิธีใช้ฟังก์ชันเหล่านี้จากวัตถุประสงค์ -c
ฟังก์ชั่นเหล่านี้ได้รับการทดสอบอย่างดีและน่าเชื่อถือซึ่งแตกต่างจากการใช้งานหลายอย่างที่คุณอาจพบในการโพสต์ทางอินเทอร์เน็ตแบบสุ่ม libresolv.dylib
อย่าลืมที่จะเชื่อมโยงกับ
เนื่องจากดูเหมือนว่าจะเป็นหมายเลขหนึ่งของ Google ที่ได้รับความนิยมในการเข้ารหัส base64 และ iphone ฉันรู้สึกเหมือนแบ่งปันประสบการณ์ของฉันกับข้อมูลโค้ดด้านบน
มันใช้งานได้ แต่มันช้ามาก มาตรฐานในภาพแบบสุ่ม (0.4 mb) ใช้เวลา 37 วินาทีบน iPhone มาตรฐาน เหตุผลหลักน่าจะเป็นเวทมนตร์ OOP ทั้งหมด - ถ่าน NSStrings เดียว ฯลฯ ซึ่งจะถูกลบอัตโนมัติหลังจากการเข้ารหัสเสร็จสิ้น
ข้อเสนอแนะอื่นที่โพสต์ที่นี่ (ab) ใช้ไลบรารี openssl ซึ่งรู้สึกเหมือน overkill
รหัสด้านล่างใช้เวลา 70 มิลลิวินาที - นั่นคือความเร็ว 500 ครั้ง นี่ใช้การเข้ารหัส base64 เท่านั้น (การถอดรหัสจะตามมาทันทีที่ฉันพบ)
+ (NSString *) base64StringFromData: (NSData *)data length: (int)length {
int lentext = [data length];
if (lentext < 1) return @"";
char *outbuf = malloc(lentext*4/3+4); // add 4 to be sure
if ( !outbuf ) return nil;
const unsigned char *raw = [data bytes];
int inp = 0;
int outp = 0;
int do_now = lentext - (lentext%3);
for ( outp = 0, inp = 0; inp < do_now; inp += 3 )
{
outbuf[outp++] = base64EncodingTable[(raw[inp] & 0xFC) >> 2];
outbuf[outp++] = base64EncodingTable[((raw[inp] & 0x03) << 4) | ((raw[inp+1] & 0xF0) >> 4)];
outbuf[outp++] = base64EncodingTable[((raw[inp+1] & 0x0F) << 2) | ((raw[inp+2] & 0xC0) >> 6)];
outbuf[outp++] = base64EncodingTable[raw[inp+2] & 0x3F];
}
if ( do_now < lentext )
{
char tmpbuf[2] = {0,0};
int left = lentext%3;
for ( int i=0; i < left; i++ )
{
tmpbuf[i] = raw[do_now+i];
}
raw = tmpbuf;
outbuf[outp++] = base64EncodingTable[(raw[inp] & 0xFC) >> 2];
outbuf[outp++] = base64EncodingTable[((raw[inp] & 0x03) << 4) | ((raw[inp+1] & 0xF0) >> 4)];
if ( left == 2 ) outbuf[outp++] = base64EncodingTable[((raw[inp+1] & 0x0F) << 2) | ((raw[inp+2] & 0xC0) >> 6)];
}
NSString *ret = [[[NSString alloc] initWithBytes:outbuf length:outp encoding:NSASCIIStringEncoding] autorelease];
free(outbuf);
return ret;
}
ฉันออกจากการตัดบรรทัดเนื่องจากฉันไม่ต้องการ แต่มันเป็นเรื่องเล็กน้อยที่จะเพิ่ม
สำหรับผู้ที่สนใจในการปรับให้เหมาะสม: เป้าหมายคือการลดสิ่งที่เกิดขึ้นในลูปหลัก ดังนั้นตรรกะทั้งหมดที่จะจัดการกับ 3 ไบต์สุดท้ายจึงได้รับการปฏิบัตินอกลูป
นอกจากนี้พยายามทำงานกับข้อมูลในสถานที่โดยไม่ต้องคัดลอกไปยัง / จากบัฟเฟอร์เพิ่มเติม และลดเลขคณิตใด ๆ ให้เหลือน้อยที่สุด
สังเกตว่าบิตที่ประกอบเข้าด้วยกันเพื่อค้นหารายการในตารางจะไม่ทับซ้อนกันเมื่อถูกนำมารวมเข้าด้วยกันโดยไม่มีการขยับ การปรับปรุงที่สำคัญอาจใช้ตารางการค้นหา 256 ไบต์ 4 ตัวแยกกันและกำจัดการเปลี่ยนแปลงเช่นนี้
outbuf[outp++] = base64EncodingTable1[(raw[inp] & 0xFC)];
outbuf[outp++] = base64EncodingTable2[(raw[inp] & 0x03) | (raw[inp+1] & 0xF0)];
outbuf[outp++] = base64EncodingTable3[(raw[inp+1] & 0x0F) | (raw[inp+2] & 0xC0)];
outbuf[outp++] = base64EncodingTable4[raw[inp+2] & 0x3F];
แน่นอนว่าคุณสามารถนำมันไปใช้ประโยชน์ได้มากมาย แต่นั่นก็เกินขอบเขตที่นี่
ในการปรับปรุงที่ยอดเยี่ยมของ mvds มีสองปัญหา เปลี่ยนรหัสเป็น:
raw = tmpbuf;
inp = 0;
outbuf[outp++] = base64EncodingTable[(raw[inp] & 0xFC) >> 2];
outbuf[outp++] = base64EncodingTable[((raw[inp] & 0x03) << 4) | ((raw[inp+1] & 0xF0) >> 4)];
if ( left == 2 ) outbuf[outp++] = base64EncodingTable[((raw[inp+1] & 0x0F) << 2) | ((raw[inp+2] & 0xC0) >> 6)];
else outbuf[outp++] = '=';
outbuf[outp++] = '=';
ทางออกที่ดีกว่า:
มีฟังก์ชันในตัวใน NSData
[data base64Encoding]; //iOS < 7.0
[data base64EncodedStringWithOptions:NSDataBase64Encoding76CharacterLineLength]; //iOS >= 7.0
คนดีใจชอบมันมาก จบเกมนั้นมีข้อบกพร่องเล็กน้อยที่ฉันต้องยอมรับ นอกจากการตั้งค่า inp = 0 อย่างถูกต้องแล้วคุณควรเพิ่มขนาดของ tmpbuf เป็น 3 เช่นกัน
unsigned char tmpbuf[3] = {0,0,0};
หรือปล่อย orring ของ raw [inp + 2] ถ้าเรามี raw [inp + 2]! = 0 สำหรับ chunk นี้เราจะยังคงอยู่ในลูปแน่นอน ...
ไม่ว่าจะใช้วิธีใดคุณอาจพิจารณาทำให้บล็อกการค้นหาตารางสุดท้ายเหมือนกับบล็อกในลูปเพื่อความชัดเจน ในรุ่นสุดท้ายที่ฉันใช้ฉันทำ
while ( outp%4 ) outbuf[outp++] = '=';
ในการเพิ่ม ==
ขออภัยฉันไม่ได้ตรวจสอบสิ่งที่ RFC และควรจะทำงานได้ดีขึ้น!
ภายใต้ iOS8 และการใช้- (NSString *)base64EncodedStringWithOptions:(NSDataBase64EncodingOptions)options
NSData ในภายหลัง
#import "NSDataAdditions.h"
@implementation NSData (NSDataAdditions)
+ (NSData *) base64DataFromString: (NSString *)string {
unsigned long ixtext, lentext;
unsigned char ch, input[4], output[3];
short i, ixinput;
Boolean flignore, flendtext = false;
const char *temporary;
NSMutableData *result;
if (!string)
return [NSData data];
ixtext = 0;
temporary = [string UTF8String];
lentext = [string length];
result = [NSMutableData dataWithCapacity: lentext];
ixinput = 0;
while (true) {
if (ixtext >= lentext)
break;
ch = temporary[ixtext++];
flignore = false;
if ((ch >= 'A') && (ch <= 'Z'))
ch = ch - 'A';
else if ((ch >= 'a') && (ch <= 'z'))
ch = ch - 'a' + 26;
else if ((ch >= '0') && (ch <= '9'))
ch = ch - '0' + 52;
else if (ch == '+')
ch = 62;
else if (ch == '=')
flendtext = true;
else if (ch == '/')
ch = 63;
else
flignore = true;
if (!flignore) {
short ctcharsinput = 3;
Boolean flbreak = false;
if (flendtext) {
if (ixinput == 0)
break;
if ((ixinput == 1) || (ixinput == 2))
ctcharsinput = 1;
else
ctcharsinput = 2;
ixinput = 3;
flbreak = true;
}
input[ixinput++] = ch;
if (ixinput == 4){
ixinput = 0;
output[0] = (input[0] << 2) | ((input[1] & 0x30) >> 4);
output[1] = ((input[1] & 0x0F) << 4) | ((input[2] & 0x3C) >> 2);
output[2] = ((input[2] & 0x03) << 6) | (input[3] & 0x3F);
for (i = 0; i < ctcharsinput; i++)
[result appendBytes: &output[i] length: 1];
}
if (flbreak)
break;
}
}
return result;
}
@end
สำหรับการอัปเดตเพื่อใช้NSData (NSDataBase64Encoding)
วิธีการหมวดหมู่ใน iOS7 ดูคำตอบของฉันที่นี่: https://stackoverflow.com/a/18927627/1602729
ต่อไปนี้เป็นรุ่น Objective-C ขนาดกะทัดรัดเป็นหมวดหมู่ใน NSData ต้องใช้ความคิดเกี่ยวกับ ...
@implementation NSData (DataUtils)
static char base64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
- (NSString *)newStringInBase64FromData
{
NSMutableString *dest = [[NSMutableString alloc] initWithString:@""];
unsigned char * working = (unsigned char *)[self bytes];
int srcLen = [self length];
// tackle the source in 3's as conveniently 4 Base64 nibbles fit into 3 bytes
for (int i=0; i<srcLen; i += 3)
{
// for each output nibble
for (int nib=0; nib<4; nib++)
{
// nibble:nib from char:byt
int byt = (nib == 0)?0:nib-1;
int ix = (nib+1)*2;
if (i+byt >= srcLen) break;
// extract the top bits of the nibble, if valid
unsigned char curr = ((working[i+byt] << (8-ix)) & 0x3F);
// extract the bottom bits of the nibble, if valid
if (i+nib < srcLen) curr |= ((working[i+nib] >> ix) & 0x3F);
[dest appendFormat:@"%c", base64[curr]];
}
}
return dest;
}
@end
สามารถเพิ่มการขยายหากต้องการโดยกำหนดขอบเขตของ 'byt' ให้กว้างขึ้นและต่อท้าย 'dest' ด้วย (2-byt) "=" อักขระก่อนกลับมา
สามารถเพิ่มหมวดหมู่ไปยัง NSString ได้ดังนั้น:
@implementation NSString (StringUtils)
- (NSString *)newStringInBase64FromString
{
NSData *theData = [NSData dataWithBytes:[self UTF8String] length:[self length]];
return [theData newStringInBase64FromData];
}
@end
iOS มีวิธีการเข้ารหัสและถอดรหัส Base64 ในตัว (โดยไม่ใช้ libresolv) ตั้งแต่ iOS 4 อย่างไรก็ตามมีการประกาศใน iOS 7 SDK เท่านั้น เอกสารของ Apple ระบุว่าคุณสามารถใช้งานได้เมื่อกำหนดเป้าหมาย iOS 4 ขึ้นไป
NSData *myData = ... some data
NSString *base64String = [myData base64Encoding];
NSData *decodedData = [[NSData alloc] initWithBase64Encoding:base64String];
นี่คือตัวอย่างในการแปลงวัตถุ NSData เป็นฐาน 64 นอกจากนี้ยังแสดงวิธีไปยังวิธีอื่น (ถอดรหัสวัตถุ NSData ที่เข้ารหัส 64 ฐาน):
NSData *dataTake2 =
[@"iOS Developer Tips" dataUsingEncoding:NSUTF8StringEncoding];
// Convert to Base64 data
NSData *base64Data = [dataTake2 base64EncodedDataWithOptions:0];
// Do something with the data...
// Now convert back from Base64
NSData *nsdataDecoded = [base64Data initWithBase64EncodedData:base64Data options:0];
ใน iOS 7
NSData *data=[[NSData alloc]init];
[data base64Encoding];
ฉันทำได้โดยใช้คลาสต่อไปนี้ ..
@implementation Base64Converter
static char base64EncodingTable[64] = {
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f',
'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/'
};
+ (NSString *) base64StringFromData: (NSData *)data length: (int)length {
unsigned long ixtext, lentext;
long ctremaining;
unsigned char input[3], output[4];
short i, charsonline = 0, ctcopy;
const unsigned char *raw;
NSMutableString *result;
lentext = [data length];
if (lentext < 1)
return @"";
result = [NSMutableString stringWithCapacity: lentext];
raw = [data bytes];
ixtext = 0;
while (true) {
ctremaining = lentext - ixtext;
if (ctremaining <= 0)
break;
for (i = 0; i < 3; i++) {
unsigned long ix = ixtext + i;
if (ix < lentext)
input[i] = raw[ix];
else
input[i] = 0;
}
output[0] = (input[0] & 0xFC) >> 2;
output[1] = ((input[0] & 0x03) << 4) | ((input[1] & 0xF0) >> 4);
output[2] = ((input[1] & 0x0F) << 2) | ((input[2] & 0xC0) >> 6);
output[3] = input[2] & 0x3F;
ctcopy = 4;
switch (ctremaining) {
case 1:
ctcopy = 2;
break;
case 2:
ctcopy = 3;
break;
}
for (i = 0; i < ctcopy; i++)
[result appendString: [NSString stringWithFormat: @"%c", base64EncodingTable[output[i]]]];
for (i = ctcopy; i < 4; i++)
[result appendString: @"="];
ixtext += 3;
charsonline += 4;
if ((length > 0) && (charsonline >= length))
charsonline = 0;
}
return result;
}
@end
ในขณะที่โทรเข้า
[Base64Converter base64StringFromData:dataval length:lengthval];
แค่นั้นแหละ...
ฉันคิดว่านี่จะเป็นประโยชน์
+ (NSString *)toBase64String:(NSString *)string {
NSData *data = [string dataUsingEncoding: NSUnicodeStringEncoding];
NSString *ret = [data base64EncodedStringWithOptions:NSDataBase64Encoding64CharacterLineLength];
return ret;
}
+ (NSString *)fromBase64String:(NSString *)string {
NSData *aData = [string dataUsingEncoding:NSUTF8StringEncoding];
NSData *aDataDecoded = [[NSData alloc]initWithBase64EncodedString:string options:0];
NSString *decryptedStr = [[NSString alloc]initWithData:aDataDecoded encoding:NSUTF8StringEncoding];
return [decryptedStr autorelease];
}
ดาวน์โหลดBase64
ทำรหัสต่อไปนี้เพื่อแปลงรูปภาพเป็น base64
NSString *base64String=[UIImagePNGRepresentation(image) base64Encoding];
ตามความต้องการของคุณฉันได้สร้างตัวอย่างตัวอย่างโดยใช้Swift 4ซึ่งคุณสามารถเข้ารหัส / ถอดรหัสสตริงและรูปภาพตามความต้องการของคุณ
ฉันได้เพิ่มตัวอย่างวิธีการปฏิบัติงานที่เกี่ยวข้อง
//
// Base64VC.swift
// SOF_SortArrayOfCustomObject
//
// Created by Test User on 09/01/18.
// Copyright © 2018 Test User. All rights reserved.
//
import UIKit
import Foundation
class Base64VC: NSObject {
//----------------------------------------------------------------
// MARK:-
// MARK:- String to Base64 Encode Methods
//----------------------------------------------------------------
func sampleStringEncodingAndDecoding() {
if let base64String = self.base64Encode(string: "TestString") {
print("Base64 Encoded String: \n\(base64String)")
if let originalString = self.base64Decode(base64String: base64String) {
print("Base64 Decoded String: \n\(originalString)")
}
}
}
//----------------------------------------------------------------
func base64Encode(string: String) -> String? {
if let stringData = string.data(using: .utf8) {
return stringData.base64EncodedString()
}
return nil
}
//----------------------------------------------------------------
func base64Decode(base64String: String) -> String? {
if let base64Data = Data(base64Encoded: base64String) {
return String(data: base64Data, encoding: .utf8)
}
return nil
}
//----------------------------------------------------------------
// MARK:-
// MARK:- Image to Base64 Encode Methods
//----------------------------------------------------------------
func sampleImageEncodingAndDecoding() {
if let base64ImageString = self.base64Encode(image: UIImage.init(named: "yourImageName")!) {
print("Base64 Encoded Image: \n\(base64ImageString)")
if let originaImage = self.base64Decode(base64ImageString: base64ImageString) {
print("originalImageData \n\(originaImage)")
}
}
}
//----------------------------------------------------------------
func base64Encode(image: UIImage) -> String? {
if let imageData = UIImagePNGRepresentation(image) {
return imageData.base64EncodedString()
}
return nil
}
//----------------------------------------------------------------
func base64Decode(base64ImageString: String) -> UIImage? {
if let base64Data = Data(base64Encoded: base64ImageString) {
return UIImage(data: base64Data)!
}
return nil
}
}