How do I do base64 encoding on iOS?
我想做
对于目标C类来说,这是一个很好的用例。
对于base64编码:
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 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 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 | #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解码:
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 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 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 | #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代码的真正、非常快速的实现可以在qsUtilities库的qsstrings类中获得。我做了一个快速的基准测试:一个5.3MB的图像(jpeg)文件需要<50ms进行编码,大约需要140ms进行解码。
整个库的代码(包括base64方法)在Github上可用。
或者,如果您希望代码仅限于base64方法本身,我将它发布在这里:
首先,您需要映射表:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | 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 }; |
编码:
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 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 52 53 54 | + (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; } |
译码:
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 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 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 | + (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; } |
历史上,我们会将您引导到许多第三方base 64库中的一个库(如其他答案中所述),用于将二进制数据转换为base64字符串(以及向后转换),但ios 7现在具有本机base64编码(并公开以前私有的ios 4方法,以防您需要支持早期版本的ios)。
因此,要将
1 2 3 4 5 6 7 | NSString *string; if ([data respondsToSelector:@selector(base64EncodedStringWithOptions:)]) { string = [data base64EncodedStringWithOptions:kNilOptions]; // iOS 7+ } else { string = [data base64Encoding]; // pre iOS7 } |
如果要将base 64
1 2 3 4 5 6 7 | 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 } |
显然,如果您不需要与7.0之前的iOS版本向后兼容,那么更容易,只需分别使用
1 | NSString *string = [data base64EncodedStringWithOptions:kNilOptions]; |
然后再次回来:
1 | NSData *data = [[NSData alloc] initWithBase64EncodedString:string options:kNilOptions]; |
iOS包括对base64编码和解码的内置支持。如果你看
这些功能都经过了很好的测试和可靠的测试——不像你在随机发布的因特网上发现的许多实现。别忘了和
由于这似乎是谷歌在base64编码和iPhone上的头号热门产品,我想与上面的代码片段分享我的经验。
它可以工作,但速度非常慢。在本机iPhone上,随机图像(0.4 MB)的基准测试花费了37秒。主要原因可能是所有的OOP魔术-单字符nsstrings等,只有在编码完成后才自动释放。
这里发布的另一个建议(ab)使用了OpenSSL库,这也让人觉得杀伤力太大了。
下面的代码需要70毫秒-这是500倍的加速。这只执行base64编码(遇到解码就会立即执行)
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 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 | + (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个字节的所有逻辑都在循环之外处理。
另外,尝试就地处理数据,而不需要向缓冲区/从缓冲区进行额外的复制。把任何算术都降到最低。
观察放在一起查找表中某个条目的位,当它们在一起或不移动时不会重叠。因此,一个主要的改进可能是使用4个单独的256字节查找表并消除移位,如下所示:
1 2 3 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的卓越改进中,有两个问题。将代码更改为:
1 2 3 4 5 6 7 | 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中有一个内置函数
1 2 | [data base64Encoding]; //iOS < 7.0 [data base64EncodedStringWithOptions:NSDataBase64Encoding76CharacterLineLength]; //iOS >= 7.0 |
在IOS8下,随后使用NSdata的
很高兴人们喜欢它。我必须承认,最后一场比赛有点瑕疵。除了正确设置inp=0,您还应该将tmpbuf的大小增加到3,比如
1 | unsigned char tmpbuf[3] = {0,0,0}; |
或者省去了对原始[inp+2]的修改;如果我们有一个原始[inp+2]!=0对于这个块,我们仍然在循环中,当然…
无论采用哪种方法,为了清晰起见,您都可以考虑将最终的表查找块与循环中的查找块保持相同。在我使用的最终版本中
1 | while ( outp%4 ) outbuf[outp++] = '='; |
添加=
抱歉,我没有检查RFC和其他东西,应该做得更好!
有关在ios7中使用
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 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 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 | #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对象转换为base 64的示例。它还显示了如何进行其他操作(解码Base 64编码的NSData对象):
1 2 3 4 5 6 7 8 9 10 | 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自iOS4以来就有内置的base64编码和解码方法(不使用libresolv)。但是,它只在iOS 7 SDK中声明。Apple文档指出,在瞄准iOS 4及更高版本时,您可以使用它。
1 2 3 | NSData *myData = ... some data NSString *base64String = [myData base64Encoding]; NSData *decodedData = [[NSData alloc] initWithBase64Encoding:base64String]; |
下面是一个紧凑的Objective-C版本,作为NSData的一个类别。需要考虑一下…
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 26 27 28 29 30 31 32 33 34 35 36 | @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,从而:
1 2 3 4 5 6 7 8 9 10 | @implementation NSString (StringUtils) - (NSString *)newStringInBase64FromString { NSData *theData = [NSData dataWithBytes:[self UTF8String] length:[self length]]; return [theData newStringInBase64FromData]; } @end |
我用下节课来完成。
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 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 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 | @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 |
呼叫时
1 | [Base64Converter base64StringFromData:dataval length:lengthval]; |
就是这样…
我想这会有帮助的
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | + (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]; |
}
在IOS 7中
1 2 | NSData *data=[[NSData alloc]init]; [data base64Encoding]; |
根据您的要求,我使用Swift4创建了一个示例演示,您可以根据您的要求对字符串和图像进行编码/解码。
我还添加了相关操作的示例方法。
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
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
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85//
// 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:
\(base64String)")
if let originalString = self.base64Decode(base64String: base64String) {
print("Base64 Decoded String:
\(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:
\(base64ImageString)")
if let originaImage = self.base64Decode(base64ImageString: base64ImageString) {
print("originalImageData
\(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
}
}
下载Base64
执行以下代码以将图像转换为base64
1 | NSString *base64String=[UIImagePNGRepresentation(image) base64Encoding]; |