Python中二進(jìn)制數(shù)據(jù)處理模塊struct使用
Python中沒有二進(jìn)制類型,但是可以使用string字符串類型來存儲(chǔ)二進(jìn)制數(shù)據(jù),然后使用struct模塊來對(duì)二進(jìn)制數(shù)據(jù)進(jìn)行處理。下面將詳細(xì)描述如何使用struct模塊來處理二進(jìn)制數(shù)據(jù)。
使用struct.pack把一個(gè)整數(shù)值打包成字符串,打開Python命令行,輸入:
>>>
import struct
>>> a =0x01020304
>>> str= struct.pack(
"I", a)
>>>repr(str)
"'\\x04\\x03\\x02\\x01'"此時(shí),str為一個(gè)字符串,字符串中的內(nèi)容與整數(shù)a的二進(jìn)制存儲(chǔ)的內(nèi)容相同。
使用struct.unpack把字符串解包成整數(shù)類型,如下:
>>> b =struct.unpack(
"I", str)
>>> b
(16909060,)
在解包之后,返回一個(gè)元組類型(tuple)的數(shù)據(jù)。
如果多個(gè)數(shù)據(jù)進(jìn)行打包,可以在格式中指定打包的數(shù)據(jù)類型,然后數(shù)據(jù)通過參數(shù)傳入:
>>> a =
"hello">>> b =
"world!">>> c =2
>>> d =45.123
>>> str= struct.pack(
"5s6sif", a, b, c, d)
等價(jià)于: struct.pack_into(“5s6sif”,str, 0, a, b, c, d)
>>> str
'helloworld!\x00\x02\x00\x00\x00\xf4}4B'解包多個(gè)數(shù)據(jù)可以這樣做:
>>>parts = struct.unpack(
"5s6sif", str)
等價(jià)于: struct.unpack_from(“5s6sif”, str, 0)
>>>parts
(
'hello',
'world!', 2, 45.12300109863281)
從上可以看到浮點(diǎn)值在解包后與原來值不一樣,這是因?yàn)楦↑c(diǎn)數(shù)的精度問題導(dǎo)致的。
struct模塊中二進(jìn)制格式化表示
Format C Type Python type Standard size
x pad byte no value
c char string of length 1
b signed char integer 1
B unsigned char integer 1
? _Bool bool 1 (1)
h short integer 2
H unsigned short integer 2
i int integer 4
I unsigned int integer 4
l long integer 4
L unsigned long integer 4
q long long integer 8 (2)
Q unsigned long long integer 8 (2)
f float float 4 (3)
d double float 8 (3)
s char[] string
p char[] string
P void * integer

最后一個(gè)可以用來表示指針類型,占4個(gè)字節(jié)(32位),8個(gè)字節(jié)(64位)。
為了在與不同硬件結(jié)構(gòu)之間交換數(shù)據(jù),需要考慮字節(jié)序,如下:
字符
字節(jié)序
大小和對(duì)齊
@
本機(jī)字節(jié)序
本機(jī),本機(jī)4字節(jié)對(duì)齊
=
本機(jī)字節(jié)序
標(biāo)準(zhǔn),按原字節(jié)數(shù)對(duì)齊
<
小尾字節(jié)序
標(biāo)準(zhǔn),按原字節(jié)數(shù)對(duì)齊
>
大尾字節(jié)序
標(biāo)準(zhǔn),按原字節(jié)對(duì)齊
!
網(wǎng)絡(luò)字節(jié)序(大尾)
標(biāo)準(zhǔn),按原字節(jié)對(duì)齊
注:缺省的情況下,使用本機(jī)字節(jié)序(同@),可以通過上面的字符修改字節(jié)序。
計(jì)算格式字符串的大小函數(shù):struct.calcsize(fmt)
>>>struct.calcsize(
"ihi") 缺省為4字節(jié)對(duì)齊時(shí),長(zhǎng)度為12
12
>>>struct.calcsize(
"iih") 當(dāng)h在最后的時(shí)(此時(shí)不4字節(jié)對(duì)齊),長(zhǎng)度為10
10
>>>struct.calcsize(
"@ihi")
12
>>>struct.calcsize(
"=ihi")
10
>>>struct.calcsize(
">ihi")
10
>>>struct.calcsize(
"<ihi")
10
>>>struct.calcsize(
"!ihi")
10
注:二進(jìn)制文件打開/讀取的時(shí)候需要使用“rb”/“wb”模式以二進(jìn)制方式打開/讀取文件。
注:關(guān)于LE(little-endian)和BE(big-endian)區(qū)別:
LE—最符合人的思維的字節(jié)序,地址低位存儲(chǔ)值的低位,地址高位存儲(chǔ)值的高位。
BE—最直觀的字節(jié)序,地址低位存儲(chǔ)值的高位,地址高位存儲(chǔ)值的低位。
例如:雙字0X01020304在內(nèi)存中存儲(chǔ)方式,LE=0403 02 01,BE=01 02 03 04。