使用python进行二进制数据处理的方法。
方法一:使用struct模块,特点轻量化,简单易用。缺点就是可读性不是太好,使用小数据临时使用一下,对于大量的数据解析,写起来比较繁琐,显得有点力不从心。
import struct data = b'\x92\xaa\xbb\xcc\x11\x22\x33\x44' a,b,c,d,e = struct.unpack(">BBBBI", data) print("a=0x%x b=0x%x c=0x%x d=0x%x e=0x%x"%(a,b,c,d,e)) packData = struct.pack(">BBBBI", a, b, c, d, e) print("packData: %s"%packData)
上面的程序会按照给定的格式一次解析数据,得到的输出结果如下:
注:建议采用python3运行,python2不区分bytes和string类型,通过struct.pack()得到的结果为字符串类型,会打印出乱码。
a=0x92 b=0xaa c=0xbb d=0xcc e=0x11223344
packData: b'\x92\xaa\xbb\xcc\x11"3D'
可以看出,能够正确的解析和组装出需要的的数据。
struct常用函数原型如下:
struct的方法 | 说明 |
---|---|
pack(fmt, v1, v2…) | 按照fmt指定的格式化要求,格式化v1,v2等后续参数,返回bytes类型 |
unpack(fmt, BytesData) | 按照fmt指定的格式要求,解析出bytesData里面的数据内容,返回的是数据元组 |
pack_from(fmt, BytesData, offset) | 按照fmt指定的格式要求,解析后面的内容,从offset处开始解析,返回的是数据元组 |
这个里面的fmt表示格式化字符串,由两个部分组成,第一部分为指定大小端格式,第二部分是依次解析的格式。
大小端格式字符 | 说明 | |
---|---|---|
> | 大端模式 | 和阅读顺序一致,高字节在前(内存地址小),低字节在后(地址大)。 |
< | 小端模式 | 和大端相反,高字节在后(内存地址大),低字节在前面(地址小)。 |
@或者= | 主机默认字节序 | 和主机系统强相关,X86/X64默认为小段模式。其中@还会强制4字节对齐。 |
解析格式如下:
格式字符 | ctypes类型 | 字节数 |
---|---|---|
c | c_char | 1 |
b | c_byte | 1 |
B | c_ubyte | 1 |
h | c_short | 2 |
H | c_ushort | 2 |
i | c_int | 4 |
I | c_uint | 4 |
q | c_longlong | 8 |
Q | c_ulonglong | 8 |
f | c_float | 4 |
d | c_double | 8 |
p | c_char_p | 4(64位系统为8) |
P | c_void_p | 4(64位系统为8) |
x | c_ubyte(占位padding字节) | 1 |
方法二:使用ctypes模块高效的解析组装二进制数据,这种方法和C比较类似,也更为强大。
import ctypes class TestBig_Struct(ctypes.BigEndianStructure): _fields_=[ ('b1', ctypes.c_ubyte,1), ('b2', ctypes.c_ubyte,1), ('b3', ctypes.c_ubyte,1), ('b4', ctypes.c_ubyte,1), ('lev',ctypes.c_ubyte,4), ('BB', ctypes.c_ubyte), ('BC', ctypes.c_ubyte), ('BD', ctypes.c_ubyte), ('SS', ctypes.c_ushort), ] class Test_Struct(ctypes.Structure): _fields_=[ ('b1', ctypes.c_ubyte, 1), ('b2', ctypes.c_ubyte, 1), ('b3', ctypes.c_ubyte, 1), ('b4', ctypes.c_ubyte, 1), ('lev',ctypes.c_ubyte, 4), ('BB', ctypes.c_ubyte), ('BC', ctypes.c_ubyte), ('BD', ctypes.c_ubyte), ('SS', ctypes.c_ushort), ] if __name__ == '__main__': test = Test_Struct(); test.b1 = 1; test.b2 = 0; test.b3 = 0; test.b4 = 1; test.lev = 2; test.BB = 0xAA; test.BC = 0xBB; test.BD = 0xCC; test.SS = 0xEEFF; print ("defEndian", ctypes.string_at(ctypes.addressof(test), ctypes.sizeof(test))) test = TestBig_Struct(); test.b1 = 1; test.b2 = 0; test.b3 = 0; test.b4 = 1; test.lev = 2; test.BB = 0xAA; test.BC = 0xBB; test.BD = 0xCC; test.SS = 0xEEFF; print ("BigEndian", ctypes.string_at(ctypes.addressof(test), ctypes.sizeof(test))) ctypes.memmove(ctypes.addressof(test), b'\x92\xaa\xbb\xcc\xee\xff', ctypes.sizeof(test)); print ("b1:%x"%test.b1) print ("b2:%x"%test.b2) print ("b3:%x"%test.b3) print ("b4:%x"%test.b4) print ("lev:%x"%test.lev) print ("BB:%x"%test.BB) print ("BC:%x"%test.BC) print ("BD:%x"%test.BD) print ("SS:%x"%test.SS) with open("out.bin", "wb") as f: f.write(ctypes.string_at(ctypes.addressof(test), ctypes.sizeof(test)));
从上面的实例,可以看出来,这个就是采用类似与C结构体的方式,直接解析映射来解析和组装数据。十分的强大。这个实例程序的运行结果如下。
defEndian b')\xaa\xbb\xcc\xff\xee'
BigEndian b'\x92\xaa\xbb\xcc\xee\xff'
b1:1
b2:0
b3:0
b4:1
lev:2
BB:aa
BC:bb
BD:cc
SS:eeff
其中out.bin文件中保存的数据,以十六进制查看如下:
92 aa bb cc ee ff
标签:struct,python,print,案例,ctypes,test,ubyte,解析 From: https://www.cnblogs.com/oceaning/p/17146501.html