1. 程式人生 > 其它 >16進位制轉base64_第十一章(第3節):base64

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 解碼還原,這樣也是可以的,請編碼完成這個試驗。

閱讀原文:

base64​www.birdpython.com 80b5e747bb54d03eb247d7b6f2608afb.png