最近有小伙伴问我,它的一串 e25hbWU6IuW8gOW/gyIsdHlwZTo5MSxzb3VyY2U6NH0
使用以下代码 decode 返回 nil,但是在线上 decode 就能得到正确的结果
NSData *data = [[NSData alloc]initWithBase64EncodedString:source options:0];
return [[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding];
一段代码乍看是对的,并没有什么错误,所以我们先看看 Base64 的编解码规则吧
- Base64 组成部分
字符组成部分包括:26个大写英文字母(A-Z),26个小写英文字母(a-z),10个数字(0-9),1个 "/",一个 "+",和起来刚好64个字符,其实还有一个作为垫字的 "=",所以总的其实是65个字符
- Base64 编码对应的符号表
字符 | 编码 | 字符 | 编码 | 字符 | 编码 | 字符 | 编码 | 字符 | 编码 | 字符 | 编码 | 字符 | 编码 | 字符 | 编码 | |||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
A | 0 | I | 8 | Q | 16 | Y | 24 | g | 32 | o | 40 | w | 48 | 4 | 56 | |||||||
B | 1 | J | 9 | R | 17 | Z | 25 | h | 33 | p | 41 | x | 49 | 5 | 57 | |||||||
C | 2 | K | 10 | S | 18 | a | 26 | i | 34 | q | 42 | y | 50 | 6 | 58 | |||||||
D | 3 | L | 11 | T | 19 | b | 27 | j | 35 | r | 43 | z | 51 | 7 | 59 | |||||||
E | 4 | M | 12 | U | 20 | c | 28 | k | 36 | s | 44 | 0 | 52 | 8 | 60 | |||||||
F | 5 | N | 13 | V | 21 | d | 29 | l | 37 | t | 45 | 1 | 53 | 9 | 61 | |||||||
G | 6 | O | 14 | W | 22 | e | 30 | m | 38 | u | 46 | 2 | 54 | + | 62 | |||||||
H | 7 | P | 15 | X | 23 | f | 31 | n | 39 | v | 47 | 3 | 55 | / | 63 |
-
Base64 编码规则
每3个字符转化为4个字符(3 * 8 * N = 4 * 6 * (n + num('=') ) ),6 位满足 64 个字符表示- 每 3 个字节分为 1 组,即 24 个二进制位
- 24 个二进制位再分为 4 组,每组 6 个二进制位
- 最后一组不满 6 个二进制位,在其后补 0
- 根据上表,每组的对应符号组合即可
- 1-4步骤完成后,发现组合的字符个数为n,若
n % 4 != 0
则,在末尾补充4 - (n % 4)
个=
,酱紫组合起来即 Base64字符
N % 3 == 0的情况
解码前字串: a o c
对应ASCII: 01100001 01101111 01100011
每6位分割: 011000 010110 111101 100011
10进制值: 24 22 61 35
Base64对应字符:Y W 9 j
最后的 Base64 字符串:YW9j
- N % 3 != 0的情况(假设等于1,2的情况类似)
解码前字串: a o c d
对应ASCII: 01100001 01101111 01100011 01100100
每6位分割: 011000 010110 111101 100011 011001 000000(4个0补足)
10进制值: 24 22 61 35 25 0
Base64对应字符:Y W 9 j | Z A = = (2个=补足)
最后的 Base64 字符串:YW9jZA==
- 编码
- (NSString *)base64EncodeString {
NSData *data = [self dataUsingEncoding:NSUTF8StringEncoding];
return [data base64EncodedStringWithOptions:0];
}
- 解码
从上面的编码规则就可以反推解码过程了,而这其中可能拿到非标准的 Base64 字串,那就是可能没有补足=
,所以处理过程中,需要为非标准的 Base64 字串补足=
- (NSString *)base64DecodeString {
NSInteger dMod = self.length % 4;
NSString *base64Str = self;
if (dMod) {
base64Str = [base64Str stringByAppendingString:[@"====" substringFromIndex:dMod]];
}
NSData *data = [[NSData alloc]initWithBase64EncodedString:base64Str options:0];
return [[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding];
}
所以朋友的
e25h bWU6 IuW8 gOW/ gyIs dHlw ZTo5 MSxz b3Vy Y2U6 NH0
补足 =
即可
e25h bWU6 IuW8 gOW/ gyIs dHlw ZTo5 MSxz b3Vy Y2U6 NH0=
其实这个了解编码规则的话就能很快跟踪解决,所以仅当作一点记录吧