python struct模块--字节流转化

简介

python strtuct模块主要在Python中的值于C语言结构之间的转换。可用于处理存储在文件或网络连接(或其它来源)中的二进制数据。

主要函数

函数名返回类型描述
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)占用多少字节的内存,注意对齐方式

其中最常用的函数为:pack()unpack()

格式字符

fmt格式有以下定义:

FormatC TypePython字节数
xpad byte (填充字节)no value
ccharstring of length 11
bsigned charinteger1
Bunsigned charinteger1
_Boolbool1
hshortinteger2
Hunsigned shortinteger2
iintinteger4
I(大写的i)unsigned intinteger4
l(小写的L)longinteger4
Lunsigned longinteger4
qlong longinteger8
Qunsigned long longinteger8
ffloatfloat4
ddoublefloat8
schar[]bytes
pchar[]bytes
Pvoid *integer

1.  c,s和p按照bytes对象执行转码操作,但是在使用UTF-8编码时,也支持str对象。
2.  _Bool在C99中定义,如果没有这个类型,则将这个类型视为char,一个字节;
3.  q和Q只适用于64位机器;
4.  每个格式前可以有一个数字,表示这个类型的个数,如s格式表示一定长度的字符串,4s表示长度为4的字符串;4i表示四个int;
5.  P用来转换一个指针,其长度和计算机相关;
6.  f和d的长度和计算机相关;

示例:

import struct

// ">I"的意思是:
// >表示字节顺序是大端(big-endian),也就是网络序,I表示4字节无符号整数。
// 后面的参数个数要和处理指令一致。
b = struct.pack('>I', 1024)
print(b)

// ">IH"的说明,后面的bytes依次变为I:4字节无符号整数 和 H:2字节无符号整数。
i = struct.unpack(">IH", b"\xf0\xf0\xf0\xf0\x80\x80")
print(i)

输出:

b'\x00\x00\x04\x00'
(4042322160, 32896)

对齐方式

为了同c中的结构体交换数据,还要考虑c或c++编译器使用了字节对齐,通常是以4个字节为单位的32位系统,故而struct根据本地机器字节顺序转换.可以用格式中的第一个字符(">"等)来改变对齐方式.定义如下:

CharacterByte orderSizeAlignment
@(默认)本机本机本机,凑够4字节
=本机标准none,按原字节数
<小端标准none,按原字节数
>大端标准none,按原字节数
!network(大端)标准none,按原字节数

如果不懂大小端,见大小端参考网址.

实例

1.通常的打包和解包

# 打包和解包
import struct
import binascii
 
values = (1, b'good', 1.22)  # 查看格式化对照表可知,字符串必须为字节流类型。
s = struct.Struct('I4sf')
packed_data = s.pack(*values)
unpacked_data = s.unpack(packed_data)

print('Original values:', values)
print('Format string :', s.format)
print('Uses :', s.size, 'bytes')
print('Packed Value :', binascii.hexlify(packed_data)) # 字节流和ascii转换
print('Unpacked Type :', type(unpacked_data), ' Value:', unpacked_data)

输出:

b'\x01\x00\x00\x00good\xf6(\x9c?'
Original values: (1, b'good', 1.22)
Format string : I4sf
Uses : 12 bytes
Packed Value : b'01000000676f6f64f6289c3f'
Unpacked Type : <class 'tuple'>  Value: (1, b'good', 1.2200000286102295)

2.使用buffer来进行打包和解包
使用通常的方式来打包和解包会造成内存的浪费,所以python提供了buffer的方式:

# 通过buffer方式打包和解包
import struct
import binascii
import ctypes

values = (1, b'good', 1.22)  # 查看格式化字符串可知,字符串必须为字节流类型。
s = struct.Struct('I4sf')
buff = ctypes.create_string_buffer(s.size)
s.pack_into(buff, 0, *values)
unpacked_data = s.unpack_from(buff, 0)

print('Original values:', values)
print('Format string :', s.format)
print('buff :', buff)
print('Packed Value :', binascii.hexlify(buff))
print('Unpacked Type :', type(unpacked_data), ' Value:', unpacked_data)

输出:

Original values: (1, b'good', 1.22)
Format string : I4sf
buff : <ctypes.c_char_Array_12 object at 0x104c061e0>
Packed Value : b'01000000676f6f64f6289c3f'
Unpacked Type : <class 'tuple'>  Value: (1, b'good', 1.2200000286102295)

针对buff对象进行打包和解包,避免了内存的浪费。这里使用到了函数ctypes.create_string_buffer(init_or_size,size = None)创建可变字符缓冲区。
返回的对象是c_char的ctypes数组。init_or_size必须是一个整数,它指定数组的大小,或者用于初始化数组项的字节对象。

3.使用buffer方式来打包多个对象

values1 = (1, b'good', 1.22)  # 查看格式化字符串可知,字符串必须为字节流类型。
values2 = (b'hello', True)
s1 = struct.Struct('I4sf')
s2 = struct.Struct('5s?')
buff = ctypes.create_string_buffer(s1.size + s2.size)
s1.pack_into(buff, 0, *values1)
s2.pack_into(buff, s1.size, *values2)
unpacked_data_s1 = s1.unpack_from(buff, 0)
unpacked_data_s2 = s2.unpack_from(buff, s1.size)

print('Original values1:', values1)
print('Original values2:', values2)
print('buff :', buff)
print('Packed Value :', binascii.hexlify(buff))
print('Unpacked Type :', type(unpacked_data_s1), ' Value:', unpacked_data_s1)
print('Unpacked Type :', type(unpacked_data_s2), ' Value:', unpacked_data_s2)

输出:

Original values1: (1, b'good', 1.22)
Original values2: (b'hello', True)
buff : <ctypes.c_char_Array_18 object at 0x10483a840>
Packed Value : b'01000000676f6f64f6289c3f68656c6c6f01'
Unpacked Type : <class 'tuple'>  Value: (1, b'good', 1.2200000286102295)
Unpacked Type : <class 'tuple'>  Value: (b'hello', True)

参考:https://www.cnblogs.com/leomei91/p/7602603.html

  • 2
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值