python之struct详解
⽤处
1. 按照指定格式将Python数据转换为字符串,该字符串为字节流,如⽹络传输时,不能传输int,此时先将int转化为字节流,然后再发送;
2. 按照指定格式将字节流转换为Python指定的数据类型;
3. 处理⼆进制数据,如果⽤struct来处理⽂件的话,需要⽤’wb’,’rb’以⼆进制(字节流)写,读的⽅式来处理⽂件;
4. 处理c语⾔中的结构体;
struct模块中的函数
函数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)占⽤多少字节的内存,注意对齐⽅式
格式化字符串
当打包或者解包的时,需要按照特定的⽅式来打包或者解包.该⽅式就是格式化字符串,它指定了数据类型,除此之外,还有⽤于控制字节顺序、⼤⼩和对齐⽅式的特殊字符.
对齐⽅式
为了同c中的结构体交换数据,还要考虑c或c++编译器使⽤了字节对齐,通常是以4个字节为单位的32位系统,故⽽struct根据本地机器字节顺序转换.可以⽤格式中的第⼀个字符来改变对齐⽅式.定义如下
Character Byte order Size Alignment
@(默认)本机本机本机,凑够4字节
=本机标准none,按原字节数
<⼩端标准none,按原字节数
>⼤端标准none,按原字节数
!network(⼤端)标准none,按原字节数
如果不懂⼤⼩端,见.
格式符
格式符C语⾔类型Python类型Standard size
x pad byte(填充字节)no value
c char string of length 11
b signed char integer1
B unsigned char integer1
_Bool bool1
h short integer2
H unsigned short integer 2i int
integer 4I(⼤写的i)unsigned int integer 4l(⼩写的L)long
integer 4L unsigned long long 4q long long
long 8Q unsigned long long long 8f float float 4d double float 8s char[]string  p char[]string  P
void *
long
格式符C语⾔类型
Python类型Standard size 注- -!
1. _Bool在C99中定义,如果没有这个类型,则将这个类型视为char,⼀个字节;
2. q和Q只适⽤于64位机器;
3. 每个格式前可以有⼀个数字,表⽰这个类型的个数,如s格式表⽰⼀定长度的字符串,4s表⽰长度为4的字符串;4i表⽰四个int;
4. P⽤来转换⼀个指针,其长度和计算机相关;
5. f和d的长度和计算机相关;
进制转化:
Python 没有专门处理字节的数据类型。但由于b'str'可以表⽰字节,所以,字节数组=⼆进制str 。⽽在C 语⾔中,我们可以很⽅便地⽤struct 、union 来处理字节,以及字节和int ,float 的转换。
在Python 中,⽐⽅说要把⼀个32位⽆符号整数变成字节,也就是4个长度的bytes ,你得配合位运算
符这么写:
# 获取⽤户输⼊⼗进制数dec = int (input ("输⼊数字:"))print ("⼗进制数为:", dec )
print ("转换为⼆进制为:", bin (dec ))print ("转换为⼋进制为:", oct (dec ))print ("转换为⼗六进制为:", hex (dec ))
>>> n = 10240099
>>> b1 = (n & 0xff000000) >> 24
>>> b2 = (n & 0xff0000) >> 16
>>> b3 = (n & 0xff00) >> 8
>>> b4 = n & 0xff
>>> bs = bytes([b1, b2, b3, b4])
>>> bs
b'\x00\x9c@c'
⾮常⿇烦。如果换成浮点数就⽆能为⼒了。
好在Python提供了⼀个struct模块来解决bytes和其他⼆进制数据类型的转换。
struct的pack函数把任意数据类型变成bytes:
>>> import struct
>>> struct.pack('>I', 10240099)
b'\x00\x9c@c'
pack的第⼀个参数是处理指令,'>I'的意思是:
>表⽰字节顺序是big-endian,也就是⽹络序,I表⽰4字节⽆符号整数。
后⾯的参数个数要和处理指令⼀致。
struct
阅读: 58181
准确地讲,Python没有专门处理字节的数据类型。但由于b'str'可以表⽰字节,所以,字节数组=⼆进制str。⽽在C语⾔中,我们可以很⽅便地⽤struct、union来处理字节,以及字节和int,float的转换。
在Python中,⽐⽅说要把⼀个32位⽆符号整数变成字节,也就是4个长度的bytes,你得配合位运算符这么写:
>>> n = 10240099
>>> b1 = (n & 0xff000000) >> 24
>>> b2 = (n & 0xff0000) >> 16
>>> b3 = (n & 0xff00) >> 8
>>> b4 = n & 0xff
>>> bs = bytes([b1, b2, b3, b4])
>>> bs
b'\x00\x9c@c'
⾮常⿇烦。如果换成浮点数就⽆能为⼒了。
好在Python提供了⼀个struct模块来解决bytes和其他⼆进制数据类型的转换。
struct的pack函数把任意数据类型变成bytes:
>>> import struct
>>> struct.pack('>I', 10240099)
b'\x00\x9c@c'
pack的第⼀个参数是处理指令,'>I'的意思是:
>表⽰字节顺序是big-endian,也就是⽹络序,I表⽰4字节⽆符号整数。
后⾯的参数个数要和处理指令⼀致。
unpack把bytes变成相应的数据类型:
>>> struct.unpack('>IH', b'\xf0\xf0\xf0\xf0\x80\x80')
(4042322160, 32896)
根据>IH的说明,后⾯的bytes依次变为I:4字节⽆符号整数和H:2字节⽆符号整数。
所以,尽管Python不适合编写底层操作字节流的代码,但在对性能要求不⾼的地⽅,利⽤struct就⽅便多了。
struct模块定义的数据类型可以参考Python官⽅⽂档:
Windows的位图⽂件(.bmp)是⼀种⾮常简单的⽂件格式,我们来⽤struct分析⼀下。
⾸先⼀个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'
BMP格式采⽤⼩端⽅式存储数据,⽂件头的结构按顺序如下:
两个字节:'BM'表⽰Windows位图,'BA'表⽰OS/2位图;⼀个4字节整数:表⽰位图⼤⼩;⼀个4字节整数:保留位,始终为0;⼀个4字节整数:实际图像的偏移量;⼀个4字节整数:Header的字节数;⼀个4字节整数:图像宽度;⼀个4字节整数:图像⾼度;⼀个2字节整数:始终为1;⼀个2字节整数:颜⾊数。
所以,组合起来⽤unpack读取:
>>> struct.unpack('<ccIIIIIIHH', s)
(b'B', b'M', 691256, 0, 54, 40, 640, 360, 1, 24)
结果显⽰,b'B'、b'M'说明是Windows位图,位图⼤⼩为640x360,颜⾊数为24。
请编写⼀个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 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("这不是位图⽂件")
if __name__ == '__main__':
bmp_info(bmp_data)
print('ok')
>>> from struct import*
>>> 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
Unpacked fields can be named by assigning them to variables or by wrapping the result in a named tuple:
>>>
>>> record =b'raymond  \x32\x12\x08\x01\x08'
>>> name, serialnum, school, gradelevel = unpack('<10sHHb', record)
>>> from collections import namedtuple
>>> Student = namedtuple('Student', 'name serialnum school gradelevel')
>>> Student._make(unpack('<10sHHb', record))
Student(name=b'raymond  ', serialnum=4658, school=264, gradelevel=8)
The ordering of format characters may have an impact on size since the padding needed to satisfy alignment requirements is different:
>>>
>>> pack('ci', b'*', 0x12131415)
b'*\x00\x00\x00\x12\x13\x14\x15'
>>> pack('ic', 0x12131415, b'*')c语言struct头文件
b'\x12\x13\x14\x15*'
>>> calcsize('ci')
8
>>> calcsize('ic')
5

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。