鳴謝CSDN文章:https://blog.csdn.net/believesoul/article/details/84100616
一、言簡意賅理解Base64編碼
就是將以“字節”為單位的二進制數據,轉換為肉眼可見的64個“可打印字符”字符串的編碼方法。
啥是以“字節”為單位的二進制數據???
長得類似這個樣子:
b'C\xe8\xaf\xad\xe8\xa8\x80\xe4\xb8\xad\xe6\x96\x87\xe7\xbd\x918\xe5\xb2\x81\xe4\xba\x86' = bytes('C語言中文網8歲了', encoding='UTF-8')
詳見:https://www.cnblogs.com/zhangmingda/p/14123752.html
二、為啥要做編碼轉換?
答:一般用於在HTTP協議下傳輸二進制數據,由於HTTP協議是文本協議,所以在HTTP協議下傳輸二進制數據需要將二進制數據轉換為字符數據。然而直接轉換是不行的。因為網絡傳輸只能傳輸可打印字符。
這玩意只是編碼,不是加密,但是肉眼看不出原始內容
三、轉換為哪64個可打印字符?
答:是ASCII碼里面95個可打印字符中篩選出了64個:即后面括號內 [0-9a-zA-Z+/=] 即數字0到9,大小寫字母 和 +/= 實際為65個可打印字符。
具體什么是可打印字符?在ASCII碼中規定,0-31、128這33個字符屬於控制字符,32-127這95個字符屬於可打印字符,也就是說網絡傳輸只能傳輸這95個字符,不在這個范圍內的字符無法傳輸。那么該怎么才能傳輸其他字符呢?其中一種方式就是使用Base64。
Base64,就是使用64個可打印字符來表示二進制數據的方法。這64個字符中包括大小寫字母、數字、+和/,還有用來補缺的特殊字符=。
注意:由於base64編碼用了8位字符來表示信息中的6個位,所以base64編碼字符串大約比原始值擴大了33%。
Base64的索引與對應字符的關系如下表所示:
也就是說,如果將索引轉換為對應的二進制數據的話需要至多6個Bit。然而ASCII碼需要8個Bit來表示,那么怎么使用6個Bit來表示8個Bit的數據呢?6個Bit當然不能存儲8個Bit的數據,但是4×6個Bit可以存儲3×8個Bit的數據啊!如下表所示:
可以看到“Son”通過Base64編碼轉換成了“U29u”。這是剛剛好的情況,3個ASCII字符剛好轉換成對應的4個Base64字符。但是,當需要轉換的字符數不是3的倍數的情況下該怎么辦呢?Base64規定,當需要轉換的字符不是3的倍數時,一律采用補0的方式湊足3的倍數,具體如下表所示:
每6個Bit為一組,第一組轉換后為字符“U”,第二組末尾補4個0轉換后為字符“w”。剩下的使用“=”替代。即字符“S”通過Base64編碼后為“Uw==”。這就是Base64的編碼過程。
如果要編碼的二進制數據不是3的倍數,最后會剩下1個或2個字節怎么辦?Base64用\x00字節在末尾補足后,再在編碼的末尾加上1個或2個=號,表示補了多少字節,解碼的時候,會自動去掉。
這是字節的位總數不是6的倍數的情況,當剩下4位時,我們需要補2個=湊齊8的倍數;當剩下的是2位時,我們需要補齊1個 = 抽泣8的倍數。
四、Base64怎么用?
Python3計算Base64
import base64 str1 = "hello world!" base64.encodebytes(str1.encode()) b'aGVsbG8gd29ybGQh\n' base64.encodebytes(str1.encode()).decode() 'aGVsbG8gd29ybGQh\n' base64.encodebytes(str1.encode()).decode('utf-8') 'aGVsbG8gd29ybGQh\n'
Java計算Base64,使用的時候直接調用內部模塊即可。具體代碼如下所示:
package com.first; import org.junit.Test; import java.io.UnsupportedEncodingException; import java.util.Base64; public class Test { @Test public void test() throws UnsupportedEncodingException { // 編碼 String encode = Base64.getEncoder().encodeToString("So".getBytes("UTF-8")); System.out.println(encode); // 解碼 byte[] decode = Base64.getDecoder().decode(encode); System.out.println(new String(decode, "UTF-8")); } }
五、Base64的相關點
- 首先這算法是編碼,不是壓縮,編碼后只會增加字節數;字節數會成為原字節數的4/3;
- 算法簡單, 幾乎不會影響效率;
- 算法可逆, 解碼很方便, 不用於私密信息通信;
- 雖然解碼方便, 但畢竟編碼了, 肉眼還是不能直接看出原始內容;
- 加密后的字符串只有[0-9a-zA-Z+/=],不可打印字符(包括轉移字符)也可傳輸;