16進位制轉base64_第十一章(第3節):base64
技術標籤:16進位制轉base64
我們知道在計算機中任何資料都是按位元組儲存的,有的複雜的資料(比如漢字)可能由多個位元組表示,簡單(比如單個英文字元)的由 1 個位元組表示,位元組是記憶體中基本的儲存單位。
我們知道一個位元組可表示的範圍是 0 ~ 255(十六進位制:0x00 ~ 0xFF), 其中 ascii 值的範圍為 0 ~ 127(十六進位制:0x00 ~ 0x7F);而超越 ascii 範圍的 128~255(十六進位制:0x80 ~ 0xFF)之間的值是不可見字元。當然也並不是所有的 ascii 都是可見的,ascii 中只有 95 個可見字元(範圍為 32 ~ 126),其餘的 ascii 為不可見字元,本節後面我們會列出所有可見的 ascii 和 不可見的 ascii。
當不可見字元在網路上傳輸時,比如說從 A 計算機傳到 B 計算機,往往要經過多個路由裝置,由於不同的裝置(特指老的路由裝置)對字元的處理方式有一些不同,這樣那些不可見字元就有可能被處理錯誤,這是不利於傳輸的。所以就先把資料先做一個 base64 編碼,統統變成可見字元,也就是 ascii 碼可表示的可見字元,確保資料可靠傳輸。base64 的內容是有 0 ~9,a ~z,A ~Z,+,/組成,正好 64 個字元,這些字元是在 ascii 可表示的範圍內,屬於 95 個可見字元的一部分。
對於現在路由裝置,只要是文字字元(無論是否是可見字元)都可以直接在網路上傳輸。注意,由於二進位制格式的資料(圖片,音訊,視訊,語音等非文字字元), 無法直接在網路上傳輸,我們一般都要把這些二進位制資料轉為文字字元後進行網路傳輸。而 base64 可以把這些二進位制資料轉為文字字元,並且 base64為了相容早期的老的路由器,還轉化為了可見的文字字元,當然,對於現在的路由器來說,只要是文字字元就可以通過網路傳輸。
在企業開發中,我們只要遵守一個好的習慣就可以了:對於文字字元傳輸,我們先序列化,然後再通過網路傳送;對於二進位制資料(圖片,音訊,視訊,語音等非文字字元),我們先用 base64 編碼成文字字元,然後序列化後再通過網路傳送。大家可能要問,只要是文字字元不就可以直接通過網路傳輸了嗎,為什麼還要序列化?在此,我再告訴大家,你專案中要傳輸的資料不只有字串吧,應該還需要包容其它型別的資料,通訊雙方約定的就是傳送的東西都是序列化後資料,這樣方便對通訊雙方的資料型別進行還原。你沒必要只對其它型別的資料序列化,對字串不序列化,這樣反而增加了業務邏輯。
base64 的使用
base64 是 Python 內建模組,我們只需要 import 匯入模組就可以使用,我們可以把超越 ascii 範圍的字元用 base64 編碼為可見字元。
import base64
mystr = b"x80" # x80 換成十進位制為 128,超越了 ascii 範圍,為不可見字元
strb64 = base64.b64encode(mystr) # 編碼為 base64 的可見字元
print(strb64)
mystr = base64.b64decode(strb64)
print(mystr) # 解碼為不可見字元 x80
base64 自己有一套演算法可以把我們的字元編碼成 ascii 範圍內的字元, 當然它不關心我們給的字元是不是可見字元,如果是可見字元同樣要編碼,如果是不可見字元則會編碼成可見字元。
import base64
strone = "p".encode("utf8") # 可見字元
strtwo = "鳥".encode("utf8") # 不可見字元
print(base64.b64encode(strone)) # 編碼可見字元
print(base64.b64encode(strtwo)) # 編碼不可見字元為可見字元
base64 編碼會把 3 位元組的二進位制資料編碼為 4 位元組的文字資料,如果要編碼的二進位制資料不是 3 的倍數,最後會剩下 1 個或 2 個位元組,base64 會在編碼的末尾加上 1 個或 2 個 = 號,表示補了多少位元組,解碼的時候,會自動去掉。
import base64
strone = "p".encode("utf8") # 1個位元組
strtwo = "py".encode("utf8") # 2 個位元組
strthree = "pyt".encode("utf8") # 3 個位元組
strfour = "pyth".encode("utf8") # 4 個位元組
strfive = "pytho".encode("utf8") # 5 個位元組
strsix = "python".encode("utf8") # 6 個位元組
strseven = "老鳥".encode("utf8") # utf-8 編碼,每個漢字一般佔 3 個位元組
streight = "老鳥python".encode("utf8") # utf-8 編碼,每個漢字一般佔 3 個位元組,英文佔 1 個位元組
print(base64.b64encode(strone)) # 按 3 個位元組(缺 2 個,補齊 2 個 =)編碼成 4 個位元組 cA==
print(base64.b64encode(strtwo)) # 按 3 個位元組(缺 1 個,補齊 1 個 =)編碼成 4 個位元組 cHk=
print(base64.b64encode(strthree)) # 按 3 個位元組編碼成 4 個位元組 cHl0
print(base64.b64encode(strfour)) # 按 6 個位元組(缺 2 個,補齊 2 個 =)編碼成 8 個位元組 cHl0aA==
print(base64.b64encode(strfive)) # 按 6 個位元組(缺 1 個,補齊 1 個 =)編碼成 8 個位元組 cHl0aG8=
print(base64.b64encode(strsix)) # 按 6 個位元組編碼成 8 個位元組 cHl0aG9u
print(base64.b64encode(strseven)) # 按 6 個位元組編碼成 8 個位元組 6ICB6bif
print(base64.b64encode(streight)) # 按 12 個位元組編碼成 16 個位元組 6ICB6bifcHl0aG9u
我們可以對用 base64 編碼後的字元進行解碼。
import base64
strone = "python".encode("utf8") # 可見字元
strtwo = "老鳥".encode("utf8") # 不可見字元
dataone = base64.b64encode(strone) # 編碼可見字元 "python"
datatwo = base64.b64encode(strtwo) # 編碼不可見字元 "老鳥" 為可見字元
print(base64.b64decode(dataone)) # 解碼 base64 編碼後的字串
print(base64.b64decode(datatwo)) # 解碼 base64 編碼後的字串
由於 base64 編碼後可能出現字元 + 和 /,在網頁上傳輸資料,我們用 get 方式傳輸字串時,字元 + 和 / 在 URL 中有特殊用途,就不能直接作為引數,所以又有一種 "url safe" 的 base64 編碼,其實就是把字元 + 和 / 分別變成 - 和 _。
import base64
mystr = b"xfbxefxff"
print(base64.b64encode(mystr)) # 編碼為 ++//,但是 + 和 / 在 url 中有特殊用途,不能作為引數
print(base64.urlsafe_b64encode(mystr)) # 編碼為 --__,很好。
在網際網路上傳輸圖片,音樂,視訊,語音等等這些二進位制資料是常用的需求,我們可以用 base64 把這些二進位制資料轉為文字字元進行網路傳輸。 本節開頭部分,我們說過,最好要對文字字元進行序列化後再進行網路傳輸。所以,正規的流程是首先需要先用 base64 把圖片資料編碼為文字字元,然後序列化,最後通過網路傳送出去;另一端機器拿到這些資料,先進行反序列化,然後用 base64 進行解碼還原。
# coding:utf-8
import base64
import json
f = open("d:/test.png", "rb") # 確保你計算機中存在 d:/test.png
imgdata = f.read() # 二進位制圖片資料
f.close()
imgdatab64 = base64.b64encode(imgdata)
print imgdatab64 # 我們發現都被編碼成了 base64 的可見文字字元
jsdata = json.dumps(imgdatab64)
'''
通過網路傳輸......,
對方機器收到後,先反序列化,最後用 base64 進行解碼
'''
jsdata_recv = jsdata
imgdatab64 = json.loads(jsdata_recv)
imgdata = base64.b64decode(imgdatab64)
注意:base64 僅僅是把二進位制資料安裝一定的演算法轉化為 ascii,但不要作為加密行為。
本節重要知識點
會使用 base64 進行編解碼。
清楚 base64 使用的場景。
作業
我們在 IO 程式設計中知道,因為圖片資料有大量不可見字元,如果要把圖片資料儲存到磁碟上,需要用 "wb" 的方式寫檔案。如果我們把圖片資料用 base64 編碼成可見字元,我們用 "w" 的形式儲存到磁碟上,讀的時候在用 bases64 解碼還原,這樣也是可以的,請編碼完成這個試驗。
閱讀原文:
base64www.birdpython.com