最近有小伙伴問我,它的一串 e25hbWU6IuW8gOW/gyIsdHlwZTo5MSxzb3VyY2U6NH0 使用以下代碼 decode 返回 nil,但是在線上 decode 就能得到正確的結(jié)果
NSData *data = [[NSData alloc]initWithBase64EncodedString:source options:0];
return [[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding];
一段代碼乍看是對的,并沒有什么錯誤,所以我們先看看 Base64 的編解碼規(guī)則吧
- Base64 組成部分
字符組成部分包括:26個大寫英文字母(A-Z),26個小寫英文字母(a-z),10個數(shù)字(0-9),1個 "/",一個 "+",和起來剛好64個字符,其實(shí)還有一個作為墊字的 "=",所以總的其實(shí)是65個字符 - Base64 編碼對應(yīng)的符號表
| 字符 | 編碼 | 字符 | 編碼 | 字符 | 編碼 | 字符 | 編碼 | 字符 | 編碼 | 字符 | 編碼 | 字符 | 編碼 | 字符 | 編碼 | |||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 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 編碼規(guī)則
每3個字符轉(zhuǎn)化為4個字符(3 * 8 * N = 4 * 6 * (n + num('=') ) ),6 位滿足 64 個字符表示- 每 3 個字節(jié)分為 1 組,即 24 個二進(jìn)制位
- 24 個二進(jìn)制位再分為 4 組,每組 6 個二進(jìn)制位
- 最后一組不滿 6 個二進(jìn)制位,在其后補(bǔ) 0
- 根據(jù)上表,每組的對應(yīng)符號組合即可
- 1-4步驟完成后,發(fā)現(xiàn)組合的字符個數(shù)為n,若
n % 4 != 0則,在末尾補(bǔ)充4 - (n % 4)個=,醬紫組合起來即 Base64字符
N % 3 == 0的情況
解碼前字串: a o c
對應(yīng)ASCII: 01100001 01101111 01100011
每6位分割: 011000 010110 111101 100011
10進(jìn)制值: 24 22 61 35
Base64對應(yīng)字符:Y W 9 j
最后的 Base64 字符串:YW9j
- N % 3 != 0的情況(假設(shè)等于1,2的情況類似)
解碼前字串: a o c d
對應(yīng)ASCII: 01100001 01101111 01100011 01100100
每6位分割: 011000 010110 111101 100011 011001 000000(4個0補(bǔ)足)
10進(jìn)制值: 24 22 61 35 25 0
Base64對應(yīng)字符:Y W 9 j | Z A = = (2個=補(bǔ)足)
最后的 Base64 字符串:YW9jZA==
- 編碼
- (NSString *)base64EncodeString {
NSData *data = [self dataUsingEncoding:NSUTF8StringEncoding];
return [data base64EncodedStringWithOptions:0];
}
- 解碼
從上面的編碼規(guī)則就可以反推解碼過程了,而這其中可能拿到非標(biāo)準(zhǔn)的 Base64 字串,那就是可能沒有補(bǔ)足=,所以處理過程中,需要為非標(biāo)準(zhǔn)的 Base64 字串補(bǔ)足=
- (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
補(bǔ)足 = 即可
e25h bWU6 IuW8 gOW/ gyIs dHlw ZTo5 MSxz b3Vy Y2U6 NH0=
其實(shí)這個了解編碼規(guī)則的話就能很快跟蹤解決,所以僅當(dāng)作一點(diǎn)記錄吧