瞭解c語言的人,一定會知道struct結構體在c語言中的作用,它定義了一種結構,裏面包含不同類型的數據(int,char,bool等等),方便對某一結構對象進行處理。而在網絡通信當中,大多傳遞的數據是以二進制流(binary data)存在的。當傳遞字符串時,不必擔心太多的問題,而當傳遞諸如int、char之類的基本數據的時候,就需要有一種機制將某些特定的結構體類型打包成二進制流的字符串然後再網絡傳輸,而接收端也應該可以通過某種機制進行解包還原出原始的結構體數據。python中的struct模塊就提供了這樣的機制,該模塊的主要作用就是對python基本類型值與用python字符串格式表示的C struct類型間的轉化(This module performs conversions between Python values and C structs represented as Python strings.)
truct模塊中的函數
函數 | return | explain |
---|---|---|
pack(fmt,v1,v2…) | string | 按照給定的格式(fmt),把數據轉換成字符串(字節流),並將該字符串返回. |
pack_into(fmt,buffer,offset,v1,v2…) | None | 按照給定的格式(fmt),將數據轉換成字符串(字節流),並將字節流寫入以offset開始的buffer中.(buffer爲可寫的緩衝區,可用array模塊) |
unpack(fmt,v1,v2…..) | tuple | 按照給定的格式(fmt)解析字節流,並返回解析結果 |
pack_from(fmt,buffer,offset) | tuple | 按照給定的格式(fmt)解析以offset開始的緩衝區,並返回解析結果 |
calcsize(fmt) | size of fmt | 計算給定的格式(fmt)佔用多少字節的內存,注意對齊方式 |
1、基本的pack和unpack
實例:本例來實現往一個2進制文件中按照某種特定格式寫入數據,之後再將它讀出。
# -*- coding: utf-8 -*-
'''
數據格式爲
姓名 年齡 性別 職業
lily 18 female teacher
'''
import os
import struct
fp = open('test.bin','wb')
# 按照上面的格式將數據寫入文件中
# 這裏如果string類型的話,在pack函數中就需要encode('utf-8')
name = b'lily'
age = 18
sex = b'female'
job = b'teacher'
# int類型佔4個字節
fp.write(struct.pack('4si6s7s', name,age,sex,job))
fp.flush()
fp.close()
# 將文件中寫入的數據按照格式讀取出來
fd = open('test.bin','rb')
# 21 = 4 + 4 + 6 + 7
print(struct.unpack('4si6s7s',fd.read(21)))
fd.close()
/Library/Frameworks/Python.framework/Versions/3.5/bin/python3.5 /Users/djstava/Playground/flaskPy/test.py
(b'lily', 18, b'female', b'teacher')
Process finished with exit code 0
2、字節順序
3、利用buffer,使用pack_into和unpack_from方法(面向對象的方法)
使用二進制打包數據的場景大部分都是對性能要求比較高的使用環境。而在上面提到的pack方法都是對輸入數據進行操作後重新創建了一個內存空間用於返回,也就是說我們每次pack都會在內存中分配出相應的內存資源,這有時是一種很大的性能浪費。struct模塊還提供了pack_into() 和 unpack_from()的方法用來解決這樣的問題,也就是對一個已經提前分配好的buffer進行字節的填充,而不會每次都產生一個新對象對字節進行存儲。
還沒用到 用到再寫