1.1.用途 执行Python值和表示为bytes对象C结构之间转换,将Python基本类型转换成byte. 用于处理文件或网络中的二进制数据以及其他来源;1.2.说明: python中b'str'表示字节,字节数组=二进制str C语言用struct、union处理字节,以及字节和int,float的转换 1.3.注意: 处理与平台无关数据格式或省略隐式填充字节,用standard大小和对齐,不是native
2.1.struct函数 缓冲区参数: 缓冲区是指实现缓冲区协议并提供可读写缓冲区对象。常见bytes和bytearray支持缓冲区协议的对象可被读取 / 填充无需额外的复制bytes对象 函数:struct.pack(fmt, v1, v2, ...)用途:根据指定格式 fmt 将值 v1, v2打包成字节对象struct.pack_into(fmt, buf, offset, v1, v2, ...) 用途:按偏移量 offset 根据指定格式 fmt 将值 v1, v2打包成字节对象并写入缓冲区 说明:请注意,偏移量是必需的参数struct.unpack(fmt, buf)用途:根据格式 fmt 从缓冲区解压数据,以 tuple 的形式返回参数:缓冲区大小(字节)必须与格式所需大小相匹配,如 calcsize() 所示struct.unpack_from(fmt, buf, offset=0)用途:根据格式字符串格式从位置偏移处开始从缓冲区解包返回:元组说明:缓冲区大小(字节,减去偏移量)必须至少为格式所需大小如 calcsize() 所示struct.iter_unpack(fmt, buf)用途:根据格式字符串格式从缓冲区缓冲区迭代解压缩返回:迭代器,它将从缓冲区读取大小相同的块,直到其所有内容都被消耗掉。说明:缓冲区大小(字节)必须是格式所需大小倍数,如 calcsize()所示每次迭代都会产生格式字符串指定的元组struct.calcsize(fmt)用途:计算格式字符串所对应的结果的长度返回:与格式字符串格式对应的struct 大小(以及由此生成字节对象的大小)pack(fmt, ...)
2.2.struct模块类: class struct.Struct(format) 用途:返回一个新Struct对象,它根据格式字符串格式写入和读取二进制数据说明:创建Struct对象并调用方法比调用struct函数更有效率,因为格式字符串只需编译一次 编译结构对象支持以下方法和属性: format 用于构造此Struct对象格式字符串 size 计算结构体大小(及由pack()生成字节对象大小)对应于format 方法: pack(v1,v2,... ) 用途:同pack()函数使用编译后的格式。(len(result)将等于size) pack_into(buffer,offset,v1,v2,... ) 用途:同pack_into()函数使用编译后的格式 unpack(缓冲区) 用途:同unpack()函数使用编译后的格式。缓冲区大小以字节为单位必须相等size unpack_from(buffer,offset = 0 ) 用途:同unpack_from()函数同使用编译后格式。缓冲区大小(字节,减去偏移量) 必须至少为 size iter_unpack(缓冲区) 用途:同iter_unpack()函数使用编译后格式。缓冲区大小以字节为单位size
3.实例:# python数据类型直接转换为byte:
实例1.1:字符串 # 编码仅能用于str, 其他5中基本类型不能应用
a1 = 'str'
b1 = a1.encode('utf-8') # b'str'
s1 = b1.decode('utf-8') # 'str' 实例1.2:数字
# float不能转换
n = 10240099
b1 = (n & 0xff000000) >> 24
b2 = (n & 0xff0000) >> 16
b3 = (n & 0xff00) >> 8
b4 = n & 0xff bs = bytes([b1, b2, b3, b4])# b'\x00\x9c@c'非常麻烦
实例2:打包解包示例 实例2.1:
from struct import * # 参数'>I':字节顺序是big-endian网络序,I表示4字节无符号整数
pack('>I', 10240099) # b'\x00\x9c@c' # 参数个数要和处理指令一致
pack('hhl', 1, 2, 3) # b'\x00\x01\x00\x02\x00\x00\x00\x03'
unpack('hhl', b'\x00\x01\x00\x02\x00\x00\x00\x03') # (1, 2, 3)
calcsize('hhl') # 8 # 后面的bytes依次变为I:4字节无符号整数和H:2字节无符号整数
unpack('>IH', b'\xf0\xf0\xf0\xf0\x80\x80') # (4042322160, 32896) a = 20;b = 400
# 整数转换为字符串(字节流)
s = pack('ii', a, b)# :b'\x14\x00\x00\x00\x90\x01\x00\x00' <class 'bytes'>
print('length: ', len(s)) # 输出:length: 8字节(int类型占用4个字节) s2 = unpack('ii', s) # 格式符"i"表示转换为int,'ii'表示有两个int变量
print(s2) # 输出:(20, 400) 实例2.2:
import sys
from struct import *
from ctypes import create_string_buffer buf = create_string_buffer(12)
print(repr(buf.raw)) # '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' pack_into("iii", buf, 0, 1, 2, -1)
print(repr(buf.raw)) # b'\x01\x00\x00\x00\x02\x00\x00\x00\xff\xff\xff\xff' print(unpack_from("iii", buf, 0)) # (1, 2, -1)
实例2.3:
#解包字段可通过将它们分配给变量或通过将结果包装到指定元组中来命名: record = b'raymond \x32\x12\x08\x01\x08'
print(record) #b'raymond 2\x12\x08\x01\x08'
name, serialnum, school, gradelevel = unpack('<10sHHb', record) print('a1=%s;a2=%s;a3=%s;a4=%s'%(name, serialnum, school, gradelevel))# a1=b'raymond ';a2=4658;a3=264;a4=8 from collections import namedtuple
Student = namedtuple('Student', 'name serialnum school gradelevel')
print(Student) #<class '__main__.Student'>
a=Student._make(unpack('<10sHHb', record))
print(a) # Student(name=b'raymond ', serialnum=4658, school=264, gradelevel=8) '''
namedtuple._make 返回命名元组的新实例,用新值替换指定字段
Point = namedtuple('Point', ['x', 'y'])
t = [11, 22]
Point._make(t)#Point(x=11, y=22)
''' #以下格式'llh0l'在末尾指定两个填充字节,假定长度在4个字节边界上对齐:
a=pack('llh0l', 1, 2, 3)
print(a) #b'\x01\x00\x00\x00\x02\x00\x00\x00\x03\x00\x00\x00' 实例2.4:
string = b'test astring'
format = '5s 4x 3s'
print(struct.unpack(format, string)) # (b'test ', b'ing') string = b'he is not very happy'
format = b'2s 1x 2s 5x 4s 1x 5s'
print(struct.unpack(format, string)) # (b'he', b'is', b'very', b'happy')
实例2.5:Windows的位图文件(.bmp)
#BMP格式采用小端方式存储数据,文件头结构按顺序如下:
'''
两个字节:'BM'表示Windows位图,'BA'表示OS/2位图;
一个4字节整数:表示位图大小;
一个4字节整数:保留位,始终为0;
一个4字节整数:实际图像的偏移量;
一个4字节整数:Header的字节数;
一个4字节整数:图像宽度;
一个4字节整数:图像高度;
一个2字节整数:始终为1;
一个2字节整数:颜色数。
''' #读入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读取:
import struct
a=struct.unpack('<ccIIIIIIHH', s)
print(a) #(b'B', b'M', 691256, 0, 54, 40, 640, 360, 1, 24) #结果显示,b'B'、b'M'说明是Windows位图,位图大小为640x360,颜色数24
4.格式字符串
4.1.用途:在打包解包数据时指定数据类型;还有控制字节序,大小和对齐特殊字符 4.2.字节序大小和对齐: 默认C以机器本机格式和字节序表示,在必要时跳过填充字节进行适当对齐或根据下表格式字符串首字符指示打包数据字节序大小和对齐方式简表:
| 字符 |
字节序 |
Size |
对齐 |
备注 |
| @ |
native |
native |
native |
用本机字节序 |
| = |
native |
standard |
none |
用本机字节序,大小和对齐是标准化 |
| < |
little-endian |
standard |
none |
|
| > |
big-endian |
standard |
none |
|
| ! |
network (=大端) |
standard |
none |
网络字节序不确定时可采用 |
说明:无法指示非本机字节序(强制字节交换);只能使用适当 < 或 > 选项填充仅在连续结构成员之间自动添加。在编码结构开头或结尾没有添加填充使用非原生大小和对齐时不添加填充,例如使用 <,>,= 和 !要将结构末尾与特定类型对齐要求对齐,请用重复计数为零的该类型的代码结束格式标准尺寸仅取决于格式字符,请参阅格式字符部分中的表备注: 1)本机字节序是big-endian或 little-endian取决于主机系统:Intel x86 和 AMD64(x86-64)是 little-endian摩托罗拉 68000 和 PowerPC G5 都是大端的;ARM 和 Intel Itanium 具有可切换字节序(双端)2)查看系统字节序:sys.byteorder3)使用 C 编译器的 sizeof 表达式确定 native size 和 alignment原生大小和对齐是使用C编译器sizeof表达式确定总是与本地字节顺序相结合
4.3.格式字符
含义:根据类型C和Python值之间转换应是显而易见 “标准大小”指用标准大小打包值大小(字节)即当格式字符串以 <,>,!= 开头用本机大小时,打包值大小取决于平台简表:
| 格式 |
C类型 |
Python type |
标准大小 |
备注 |
| x |
pad byte |
no value |
|
|
| c |
char |
bytes长度1 |
1字节 |
|
| b |
signed char |
integer |
1字节 |
|
| B |
unsigned char |
integer |
1字节 |
|
| ? |
_Bool |
bool |
1字节 |
类型不可用时用a进行模拟char;True,False,0,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 |
仅C编译器支持C转换代码在本地模式或在win |
| Q |
unsigned long long |
integer |
8 |
同上 |
| n |
ssize_t |
integer |
|
仅用于本机大小(默认或@)。对于标准大小,可用适任何整数格式 |
| N |
size_t |
integer |
|
同上 |
| e |
|
float |
2 |
binary16 C不支持用uint替换 |
| f |
float |
float |
4 |
binary32 |
| d |
double |
float |
8 |
binary64不管平台使用浮点格式 |
| s |
char[] |
bytes |
|
|
| p |
char[] |
bytes |
|
|
| P |
void * |
integer |
|
仅用于本地字节序(默认或@)不能用'=' |
说明:1)'4h'==” 'hhhh'格式字符串前整数表示重复计数2)'10s'表示10字节字符串(被解释为字节长度)'10c'表示10个字符3)格式间空格被忽略; 计数及其格式不能包含空格4)对于打包,字符串将被截断或填充为空字节,以使其合适对于解包,结果字节对象总是具有指定字节数。特殊'0s'表示单一空字符串( '0c'表示0个字符)5)当值x用整数格式(一个'b', 'B','h','H','i','I','l','L', 'q','Q'),如x在有效范围之外抛异常6)'p'存储在一很短可变长度字符串固定数目字节,由计数给出。存储第一字节是字符串长度或255,以较小者为准。字符串字节在后面。如传入字符串 pack()太长(比计数减1更长)则仅count-1存储字符串前导字节。如字符串小于 count-1则填充空字节,以便使用所有字节中精确计数字节。注意对于unpack()中,'p'格式字符占用count字节,但返回字符串不能包含超过255个字节