目錄
- 二進制數(shù)據(jù)結(jié)構(gòu)Struct
- 函數(shù)與Struct類
- 打包
- 解包
- 字節(jié)序指示符
- 緩沖區(qū)
二進制數(shù)據(jù)結(jié)構(gòu)Struct
在C/C++語言中,struct被稱為結(jié)構(gòu)體。而在Python中,struct是一個專門的庫,用于處理字節(jié)串與原生Python數(shù)據(jù)結(jié)構(gòu)類型之間的轉(zhuǎn)換。
本篇,將詳細介紹二進制數(shù)據(jù)結(jié)構(gòu)struct的使用方式。
函數(shù)與Struct類
struct庫包含了一組處理結(jié)構(gòu)值得模塊級函數(shù),以及一個Struct類。格式指示符將由字符串格式轉(zhuǎn)換為一種編譯表示,這與處理正則表達式得方式類似。
這個轉(zhuǎn)換會耗費一些資源,所以創(chuàng)建一個Struct實例并再這個實例上調(diào)用方法時,只完成一次轉(zhuǎn)換,往往會更高效。
打包
Struct支持使用格式指示符將數(shù)據(jù)打包為字符串,另外支持從字符串解包數(shù)據(jù),格式指示符由表示數(shù)據(jù)類型的字符串和可選的數(shù)量及字節(jié)序指示符構(gòu)成。
下面,我們來打包一個元組,將其轉(zhuǎn)換為16進制字節(jié)序列,示例如下:
import struct
import binascii
values = (2, 'lyj'.encode('UTF-8'), 3.8)
s = struct.Struct('I 3s f')
packed_data = s.pack(*values)
print("原值:", values)
print("格式指示符:", s.format)
print("大?。?, s.size, 'bytes')
print("打包值:", binascii.hexlify(packed_data))
運行之后,效果如下:
這里的格式指示符為“I 3s f”。前面介紹array數(shù)組時,我們已經(jīng)列出過一個表格。其中I標識一個整型或長整型,3s表示3個字節(jié)字符串(lyj),f表示浮點數(shù)。
解包
struct庫使用unpack()可以從打包的表示數(shù)據(jù)中抽取數(shù)據(jù),這里直接復制上面的打包值,進行測試。示例如下:
import struct
import binascii
packed_data = binascii.unhexlify(b'020000006c796a0033337340')
s = struct.Struct('I 3s f')
unpacked_data = s.unpack(packed_data)
print("解包值:", unpacked_data)
運行之后,效果如下:
雖然使用unpack()解包基本會得到相同值,但浮點數(shù)的值有微小的差別。
字節(jié)序指示符
默認情況下,值會使用原生C庫的字節(jié)序(endianness)來編碼。Struct的字節(jié)序指示符如下表所示:
代碼 |
含義 |
@ |
原生順序 |
= |
原生標準 |
|
小端 |
> |
大端 |
! |
網(wǎng)絡順序 |
示例如下:
import struct
import binascii
values = (2, 'lyj'.encode('UTF-8'), 3.8)
endianness = [
('@', '原生順序'),
('=', '原生標準'),
('', '小端'),
('>', '大端'),
('!', '網(wǎng)絡順序'),
]
for code, name in endianness:
s = struct.Struct(code + ' I 3s f')
packed_data = s.pack(*values)
print("格式化字符串:", s.format, ' for ', name)
print("大?。?, s.size, 'bytes')
print("打包:", binascii.hexlify(packed_data))
print("解包:", s.unpack(packed_data))
運行之后,效果如下:
如果想改變字節(jié)序來編碼,如上面代碼所示,只需要改變格式串中提供一個顯式的字節(jié)序指令,就可以很容易地覆蓋這個默認選擇。
緩沖區(qū)
通常在強調(diào)性能的情況下或者向擴展模塊傳入或傳出數(shù)據(jù)時才會處理二進制打包數(shù)據(jù)。
為了避免為每個打包結(jié)構(gòu)分配一個新緩沖區(qū)所帶來的開銷,通常情況下,我們使用pack_into()和unpack_from()方法支持直接寫入預分配的緩沖區(qū)。
示例如下:
import struct
import binascii
import ctypes
import array
values = (2, 'lyj'.encode('UTF-8'), 3.8)
s = struct.Struct('I 3s f')
print("原始值:", values)
b = ctypes.create_string_buffer(s.size)
print("打包之前(緩沖區(qū)的值):", binascii.hexlify(b.raw))
s.pack_into(b, 0, *values)
print("打包之后(緩沖區(qū)的值):", binascii.hexlify(b.raw))
print("解包:", s.unpack_from(b, 0))
a = array.array('b', b'\0' * s.size)
print("打包之前(緩沖區(qū)的值):", binascii.hexlify(a))
s.pack_into(a, 0, *values)
print('打包之后(緩沖區(qū)的值):', binascii.hexlify(a))
print("解包:", s.unpack_from(a, 0))
運行之后,效果如下:
這里通過兩種方式,創(chuàng)建緩沖區(qū)。其中size屬性用于指出緩沖區(qū)需要的大小。
到此這篇關于Pytho 二進制數(shù)據(jù)結(jié)構(gòu)Struct的具體使用的文章就介紹到這了,更多相關Pytho 二進制數(shù)據(jù)結(jié)構(gòu)Struct內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
您可能感興趣的文章:- Python 數(shù)據(jù)結(jié)構(gòu)之樹的概念詳解
- python三種數(shù)據(jù)結(jié)構(gòu)及13種創(chuàng)建方法總結(jié)
- python數(shù)據(jù)結(jié)構(gòu)的排序算法
- Python內(nèi)置數(shù)據(jù)結(jié)構(gòu)列表與元組示例詳解
- python用sqlacodegen根據(jù)已有數(shù)據(jù)庫(表)結(jié)構(gòu)生成對應SQLAlchemy模型
- Python數(shù)據(jù)結(jié)構(gòu)之圖的存儲結(jié)構(gòu)詳解
- Python數(shù)據(jù)結(jié)構(gòu)之二叉排序樹的定義、查找、插入、構(gòu)造、刪除
- Python數(shù)據(jù)結(jié)構(gòu)之優(yōu)先級隊列queue用法詳解
- 詳解python數(shù)據(jù)結(jié)構(gòu)之棧stack
- Python數(shù)據(jù)結(jié)構(gòu)詳細