Python學習筆記__12.4章 struct
1、概覽
struct模塊用於解決bytes和其他二進制數據類型的轉換
1)struct的pack函數把任意數據類型變成bytes:
>>> import struct
>>> struct.pack('>I', 10240099)
b'\x00\x9c@c'
pack的參數:
第一個參數是處理指令:
'>I'的意思是:>表示字節順序是big-endian,也就是網絡字節序,I表示4字節無符號整數。
第二個參數是傳入的參數:
傳入的參數個數要和處理指令一致。
2)unpack把bytes變成相應的數據類型:
>>> struct.unpack('>IH', b'\xf0\xf0\xf0\xf0\x80\x80')
(4042322160, 32896)
根據>IH的說明,後面的bytes依次變為:
I:4字節無符號整數和 H:2字節無符號整數。
3)bmp文件的unpack
# 用畫圖,畫一個bmp文件,讀入前30個字節進行分析
>>> s = b'\x42\x4d\x38\x8c\x0a\x00\x00\x00\x00\x00\x36\x00\x00\x00\x28\x00\x00\x00\x80\x02\x00\x00\x68\x01\x00\x00\x01\x00\x18\x00'
# 用unpack讀取
>>> struct.unpack('<ccIIIIIIHH', s) # < 表示字節序是主機字節序 Little endian
(b'B', b'M', 691256, 0, 54, 40, 640, 360, 1, 24)
兩個字節:'BM'表示Windows位圖,'BA'表示OS/2位圖;
一個4字節整數:表示位圖大小;
一個4字節整數:保留位,始終為0;
一個4字節整數:實際圖像的偏移量;
一個4字節整數:Header的字節數;
一個4字節整數:圖像寬度;
一個4字節整數:圖像高度;
一個2字節整數:始終為1;
一個2字節整數:顏色數。
結果顯示,b'B'、b'M'說明是Windows位圖,位圖大小為640x360,顏色數為24。
4)參考文檔
struct模塊定義的數據類型 (https://docs.python.org/3/library/struct.html#format-characters)
Python網絡字節序和主機字節序 (https://www.linuxidc.com/Linux/2014-02/97157.htm)
2、例子
1、編寫一個bmpinfo.py,可以檢查任意文件是否是位圖文件,如果是,打印出圖片大小和顏色數
# -*- coding: utf-8 -*-
import base64, struct
bmp_data = base64.b64decode('Qk1oAgAAAAAAADYAAAAoAAAAHAAAAAoAAAABABAAAAAAADICAAASCwAAEgsAAAAAAAAAAAAA/3//f/9//3//f/9//3//f/9//3//f/9//3//f/9//3//f/9//3//f/9//3//f/9//3//f/9//3//f/9/AHwAfAB8AHwAfAB8AHwAfP9//3//fwB8AHwAfAB8/3//f/9/AHwAfAB8AHz/f/9//3//f/9//38AfAB8AHwAfAB8AHwAfAB8AHz/f/9//38AfAB8/3//f/9//3//fwB8AHz/f/9//3//f/9//3//f/9/AHwAfP9//3//f/9/AHwAfP9//3//fwB8AHz/f/9//3//f/9/AHwAfP9//3//f/9//3//f/9//38AfAB8AHwAfAB8AHwAfP9//3//f/9/AHwAfP9//3//f/9//38AfAB8/3//f/9//3//f/9//3//fwB8AHwAfAB8AHwAfAB8/3//f/9//38AfAB8/3//f/9//3//fwB8AHz/f/9//3//f/9//3//f/9/AHwAfP9//3//f/9/AHwAfP9//3//fwB8AHz/f/9/AHz/f/9/AHwAfP9//38AfP9//3//f/9/AHwAfAB8AHwAfAB8AHwAfAB8/3//f/9/AHwAfP9//38AfAB8AHwAfAB8AHwAfAB8/3//f/9//38AfAB8AHwAfAB8AHwAfAB8/3//f/9/AHwAfAB8AHz/fwB8AHwAfAB8AHwAfAB8AHz/f/9//3//f/9//3//f/9//3//f/9//3//f/9//3//f/9//3//f/9//3//f/9//3//f/9//3//f/9//38AAA==')
def bmp_info(data):
str=struct.unpack('<ccIIIIIIHH',data[:30]) #bytes類也有切片方法
if str[0]==b'B' and str[1]==b'M':
print("這是位圖文件")
return {
'width': str[-4],
'height': str[-3],
'color': str[-1]
}
else:
print("這不是位圖文件")
# 測試
bi = bmp_info(bmp_data)
assert bi['width'] == 28
assert bi['height'] == 10
assert bi['color'] == 16
print('ok')
Python學習筆記__12.4章 struct