一直以來對python的二進制數據搞不清楚。
一、二進制顯示格式與實際存儲值區別
1.二進制數據在python中以字節(bytes)類型和字節數組類型(bytearray)保存着,前者數據固定,后者不固定,可繼續添加。其每個元素為一個字節的數值,這就要求每個元素數值必須位於【0,255】之間,因為一個字節只能表示這個范圍的數據。
2.由於字節或字節數組類型元素只能處於【0,255】之間,因此要表示中文(通常是三個字節(utf-8編碼)),必須將中文轉成字節格式,下例就出錯了:
>>> b'中文'
File "<stdin>", line 1
SyntaxError: bytes can only contain ASCII literal characters.
錯誤原因是字節只能包含ASCII常量字符
解決辦法是先將中文字符轉其他類型的編碼即可,如轉成utf-8編碼:
>>> '中文'.encode('utf-8')
b'\xe4\xb8\xad\xe6\x96\x87'
這就是unicode與bytes之間相互轉化方式,我們循環這個bytes:
>>> for i in b'\xe4\xb8\xad\xe6\x96\x87':
... print(i)
...
228
184
173
230
150
135
發現字符“中”由三個8位數據構成,即228 184 173,我們將其轉化成二進制格式:
>>> bin(228)
'0b11100100'
>>> bin(184)
'0b10111000'
>>> bin(173)
'0b10101101'
發現字符“中”的utf-8編碼方式為:11100100 10111000 10101101,這也是它在計算機中存儲的方式。
3.ASCII碼能夠表示的字符(0-9a-zA-Z及一些標點符號轉義字符等)轉化成utf-8碼不發生改變,因為utf-8編碼是ASCII編碼的超集。
>>> 'afAFA!@#'.encode('utf-8')
b'afAFA!@#'
而實際上存儲的是各字符的ASCII碼值:
>>> for i in b'afAFA!@#':
... print(i)
...
97
102
65
70
65
33
64
35
當中英文混合時我們看的更清楚:
>>> '中c'.encode()
b'\xe4\xb8\xadc'
我們看到最后的字符c並沒有發生轉義成十六進制,仍然是c。
這就是說明,tytes類型顯示格式是十六進制格式,ASCII碼原樣不改變,但最終存儲的值還是對應十六進制值格式對等的二進制格式值。
始終記住:顯示的是十六進制格式,存儲的是對應的碼值。如:
>>> b'a'[0]
97
顯示的是字符a,實際上保存的是對應的ASCII碼值97.
二、binascii模塊:
binascii模塊定義了很多二進制轉化的函數。
binascii.hexlify() 將單個字符轉化成對應碼值的十六進制格式(\xxx)格式
>>> binascii.hexlify(b'\xefmm')
b'ef6d6d'
binascii.unhexlify() 兩個字符為單位,看作十六進制值,轉化成對應碼值的字符格式
>>> binascii.unhexlify(b'ef6d6d')
b'\xefmm'
因此參數里不能是基數個字符
