Base64編碼及iOS中的Base64

# 簡(jiǎn)介


Base64是一種用64個(gè)字符來表示任意二進(jìn)制數(shù)據(jù)的方法愈案。是一種編碼方法银萍,有自己的編碼表,所以稱為Base64肥隆,是因?yàn)槠涫褂?4個(gè)字符來對(duì)任意數(shù)據(jù)進(jìn)行編碼既荚,同理有Base32、Base16編碼栋艳。

用記事本打開exe恰聘、jpgpdf這些文件時(shí)吸占,我們都會(huì)看到一大堆亂碼晴叨,因?yàn)槎M(jìn)制文件包含很多無法顯示和打印的字符(ASCII表中有32個(gè)非打印控制字符),所以矾屯,如果要讓記事本這樣的文本處理軟件能處理二進(jìn)制數(shù)據(jù)兼蕊,就需要一個(gè)二進(jìn)制到字符串的轉(zhuǎn)換方法。Base64是一種最常見的二進(jìn)制編碼方法件蚕。

# 應(yīng)用場(chǎng)景


應(yīng)用:

  1. 有些文本協(xié)議不支持不可見字符的傳遞孙技,只能用ASCII編碼表中大于32的可見字符來傳遞信息(協(xié)議規(guī)定)
  2. 比如一個(gè)純文本協(xié)議,二進(jìn)制中可能會(huì)出現(xiàn)被當(dāng)做控制字符處理的部分骤坐。這樣引起傳輸失敗绪杏。
  3. 比如http協(xié)議當(dāng)中的key value字段,必須進(jìn)行URLEncode纽绍,不然出現(xiàn)的等號(hào)可能使解析失敗。同時(shí)空格也會(huì)使http請(qǐng)求解析出現(xiàn)問題势似,比如 請(qǐng)求行就是以空格來劃分的
  4. 在網(wǎng)絡(luò)上交換數(shù)據(jù)時(shí)拌夏,比如說從A地傳到B地,往往要經(jīng)過多個(gè)路由設(shè)備履因,由于不同的設(shè)備對(duì)字符的處理方式有一些不同障簿,這樣那些不可見字符就有可能被處理錯(cuò)誤,這是不利于傳輸?shù)恼てO劝褦?shù)據(jù)先做一個(gè)Base64編碼站故,統(tǒng)統(tǒng)變成可見字符,這樣出錯(cuò)的可能性就大降低了毅舆。
    對(duì)證書來說西篓,特別是根證書,一般都是作Base64編碼的憋活,因?yàn)樗诰W(wǎng)上被許多人下載岂津。電子郵件的附件一般也作Base64編碼的,因?yàn)橐粋€(gè)附件數(shù)據(jù)往往是有不可見字符的悦即。
  5. 有時(shí)在一些特殊應(yīng)用的場(chǎng)合吮成,大多數(shù)消息是純文本的橱乱,偶爾需要用這條純文本通道傳一張圖片之類的情況發(fā)生的時(shí)候,就會(huì)用到base64
  6. 某些系統(tǒng)中只能使用ASCII字符粱甫。Base64就是用來將非ASCII字符的數(shù)據(jù)轉(zhuǎn)換成ASCII字符的一種方法泳叠。

# 原理


Base64的原理很簡(jiǎn)單,首先茶宵,準(zhǔn)備一個(gè)包含64個(gè)字符的數(shù)組:

['A', 'B', 'C', ... 'a', 'b', 'c', ... '0', '1', ... '+', '/']

然后危纫,對(duì)二進(jìn)制數(shù)據(jù)進(jìn)行處理,每3個(gè)字節(jié)一組节预,一共是3x8=24bit叶摄,劃為4組,每組正好6個(gè)bit:

這樣我們得到4個(gè)數(shù)字作為索引安拟,然后查表蛤吓,獲得相應(yīng)的4個(gè)字符,就是編碼后的字符串糠赦。


Base64編碼索引表

所以会傲,Base64編碼會(huì)把3字節(jié)的二進(jìn)制數(shù)據(jù)編碼為4字節(jié)的文本數(shù)據(jù),長(zhǎng)度增加33%拙泽,好處是編碼后的文本數(shù)據(jù)可以在郵件正文淌山、網(wǎng)頁(yè)等直接顯示。

注意點(diǎn):
  • 如果要編碼的二進(jìn)制數(shù)據(jù)不是3的倍數(shù)顾瞻,最后會(huì)剩下1個(gè)或2個(gè)字節(jié)怎么辦泼疑?Base64用\x00字節(jié)在末尾補(bǔ)足后,再在編碼的末尾加上1個(gè)或2個(gè)=號(hào)荷荤,表示補(bǔ)了多少字節(jié)退渗,解碼的時(shí)候,會(huì)自動(dòng)去掉蕴纳。
# 舉例:原字符串a(chǎn)bcd

# 二進(jìn)制形式(因?yàn)槟?之后会油,剩1一個(gè)字節(jié),所以需要補(bǔ)兩個(gè)字節(jié))
01100001 01100010 01100011 01100100 00000000 00000000

# 每3個(gè)字節(jié)一組古毛,劃分為4組翻翩,每組6bit
011000 010110 001001 100011 011001 000000 000000 000000
  24     22     9      35     25      0
  Y      W      J      j      Z       A

# 需要注意,因?yàn)槲覀冄a(bǔ)了兩個(gè)字節(jié)稻薇,所以最后必然會(huì)有兩組000000嫂冻,注意,此處000000不會(huì)編碼為A颖低,而是記為=絮吵,標(biāo)志著我們?cè)谀┪惭a(bǔ)充了2個(gè)`\x00`
# 所以最后的結(jié)果為:
YWJjZA==

# 同理:當(dāng)我們補(bǔ)了1個(gè)字節(jié)時(shí),最后必然會(huì)有一組000000忱屑,此處000000也是記為=蹬敲,標(biāo)志著我們?cè)谀┪惭a(bǔ)充了1個(gè)`\x00`
abcde 編碼為 -> YWJjZGU=
  • 由于=字符也可能出現(xiàn)在Base64編碼中暇昂,但 = 用在URL、Cookie里面會(huì)造成歧義伴嗡,所以急波,很多Base64編碼后會(huì)把=去掉。
    去掉=后怎么解碼呢瘪校?因?yàn)锽ase64是把3個(gè)字節(jié)變?yōu)?個(gè)字節(jié)澄暮,所以,Base64編碼的長(zhǎng)度永遠(yuǎn)是4的倍數(shù)阱扬,因此泣懊,需要加上=把Base64字符串的長(zhǎng)度變?yōu)?的倍數(shù),就可以正常解碼了麻惶。

  • 由于標(biāo)準(zhǔn)的Base64編碼后可能出現(xiàn)字符+/馍刮,在URL中就不能直接作為參數(shù),所以又有一種"url safe"的base64編碼窃蹋,其實(shí)就是把字符+/分別變成-_
    比如:有些平臺(tái)上用的Base64 URL 是標(biāo)準(zhǔn)Base64編碼的一個(gè)變種卡啰,分別用 -、_ 替換標(biāo)準(zhǔn)Base64編碼結(jié)果中的 + 警没、 / 匈辱,并刪除結(jié)果最后的 =

  • 還可以自己定義64個(gè)字符的排列順序,這樣就可以自定義Base64編碼杀迹,不過亡脸,通常情況下完全沒有必要。

  • Base64是一種通過查表的編碼方法树酪,不能用于加密梗掰,即使使用自定義的編碼表也不行。適用于小段內(nèi)容的編碼嗅回,比如數(shù)字證書簽名、Cookie的內(nèi)容等摧茴。

# iOS中的Base64


//字符串 base64編碼
//UTF8字符串——data——base64編碼字符串
NSString *target = @"Hello!";
NSData *data = [target dataUsingEncoding:NSUTF8StringEncoding];
NSString *base64Str = [data base64EncodedStringWithOptions:0];

//UTF8字符串——data——base64绵载、UTF8編碼格式的data——base64編碼字符串
NSData * base64Data = [nsdata base64EncodedDataWithOptions:0];
NSString *ret = [[NSString alloc] initWithData:base64Data encoding:NSUTF8StringEncoding];

#pragma mark -- 關(guān)于base64EncodedDataWithOptions方法生成的Base-64, UTF-8 encoded NSData
/* Create a Base-64, UTF-8 encoded NSData from the receiver's contents using the given options.
*/
- (NSData *)base64EncodedDataWithOptions:(NSDataBase64EncodingOptions)options API_AVAILABLE(macos(10.9), ios(7.0), watchos(2.0), tvos(9.0));
從方法說明中可以看到,生成的是base64苛白、UTF8編碼的字節(jié)數(shù)組娃豹。
比如:@“hello!” 轉(zhuǎn)成NSData對(duì)象
  對(duì)應(yīng)的字節(jié)數(shù)組是 <48656c6c 6f21>(十六進(jìn)制)
進(jìn)行base64編碼
  按照上面的過程,結(jié)果字節(jié)數(shù)組是<18 06 21 44 27 06 60 33>(十進(jìn)制表示购裙,方便查Base64編碼表)懂版,對(duì)應(yīng)的字符串是SGVsbG8h
  而使用上面的iOS api,得到的字節(jié)數(shù)組是 <83 71 86 115 98 71 56 104>(十進(jìn)制表示躏率,方便查UTF8編碼表)躯畴,對(duì)應(yīng)的字符串是SGVsbG8h

# 小結(jié)


Base64是一種任意二進(jìn)制到文本字符串的編碼方法民鼓,適用于小段內(nèi)容的編碼,常用于在URL蓬抄、Cookie丰嘉、網(wǎng)頁(yè)中傳輸少量二進(jìn)制數(shù)據(jù)(如數(shù)字證書簽名、Cookie的內(nèi)容等)嚷缭。

與UTF在使用上有明顯的不同饮亏,要在多語(yǔ)言環(huán)境中通用,那就是要使用UTF阅爽,這可以理解為存儲(chǔ)數(shù)據(jù)格式路幸。用了UTF是讓大家都能識(shí)別數(shù)據(jù),不然就會(huì)亂碼付翁。

Base-64的話简肴,不是底層存儲(chǔ)格式,只是為了數(shù)據(jù)交換用胆敞。比如圖片變成字符格式着帽,這是一種應(yīng)用格式

# 參考鏈接

原文鏈接:廖雪峰的官方網(wǎng)站,本文增加了一些個(gè)人理解及iOS相關(guān)API

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末移层,一起剝皮案震驚了整個(gè)濱河市仍翰,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌观话,老刑警劉巖予借,帶你破解...
    沈念sama閱讀 217,542評(píng)論 6 504
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異频蛔,居然都是意外死亡灵迫,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,822評(píng)論 3 394
  • 文/潘曉璐 我一進(jìn)店門晦溪,熙熙樓的掌柜王于貴愁眉苦臉地迎上來瀑粥,“玉大人,你說我怎么就攤上這事三圆∧唬” “怎么了?”我有些...
    開封第一講書人閱讀 163,912評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵舟肉,是天一觀的道長(zhǎng)修噪。 經(jīng)常有香客問我,道長(zhǎng)路媚,這世上最難降的妖魔是什么黄琼? 我笑而不...
    開封第一講書人閱讀 58,449評(píng)論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮整慎,結(jié)果婚禮上脏款,老公的妹妹穿的比我還像新娘围苫。我一直安慰自己,他們只是感情好弛矛,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,500評(píng)論 6 392
  • 文/花漫 我一把揭開白布够吩。 她就那樣靜靜地躺著,像睡著了一般丈氓。 火紅的嫁衣襯著肌膚如雪周循。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,370評(píng)論 1 302
  • 那天万俗,我揣著相機(jī)與錄音湾笛,去河邊找鬼。 笑死闰歪,一個(gè)胖子當(dāng)著我的面吹牛嚎研,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播库倘,決...
    沈念sama閱讀 40,193評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼临扮,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了教翩?” 一聲冷哼從身側(cè)響起杆勇,我...
    開封第一講書人閱讀 39,074評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎饱亿,沒想到半個(gè)月后蚜退,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,505評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡彪笼,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,722評(píng)論 3 335
  • 正文 我和宋清朗相戀三年钻注,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片配猫。...
    茶點(diǎn)故事閱讀 39,841評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡幅恋,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出泵肄,到底是詐尸還是另有隱情佳遣,我是刑警寧澤,帶...
    沈念sama閱讀 35,569評(píng)論 5 345
  • 正文 年R本政府宣布凡伊,位于F島的核電站,受9級(jí)特大地震影響窒舟,放射性物質(zhì)發(fā)生泄漏系忙。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,168評(píng)論 3 328
  • 文/蒙蒙 一惠豺、第九天 我趴在偏房一處隱蔽的房頂上張望银还。 院中可真熱鬧风宁,春花似錦、人聲如沸蛹疯。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,783評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)捺弦。三九已至饮寞,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間列吼,已是汗流浹背幽崩。 一陣腳步聲響...
    開封第一講書人閱讀 32,918評(píng)論 1 269
  • 我被黑心中介騙來泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留寞钥,地道東北人慌申。 一個(gè)月前我還...
    沈念sama閱讀 47,962評(píng)論 2 370
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像理郑,于是被迫代替她去往敵國(guó)和親蹄溉。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,781評(píng)論 2 354