python pack和unpack

进阶版:https://blog.csdn.net/youand_me/article/details/78890316

Python 中的 struct 模块

from struct import *

Python 提供了三个与 pack 和 unpack 相关的函数

1

2

3

struct.pack(fmt, v1, v2, ...)

struct.unpack(fmt, string)

struct.calcsize(fmt)

第一个函数 pack 负责将不同的变量打包在一起,成为一个字节字符串。

第二个函数 unpack 将字节字符串解包成为变量。

第三个函数 calsize 计算按照格式 fmt 打包的结果有多少个字节。

pack 操作

Pack 操作必须接受一个 template string 以及需要进行 pack 一组数据,这就意味着 pack 处理操作 定长 的数据

1

2

3

4

5

6

import struct

 

a = struct.pack("2I3sI", 12, 34, "abc", 56)

b = struct.unpack("2I3sI", a)

 

print b

上面的代码将两个整数 12 和 34,一个字符串 “abc” 和一个整数 56 一起打包成为一个字节字符流,然后再解包。其中打包格式中明确指出了打包的长度: "2I" 表明起始是两个 unsigned int , "3s" 表明长度为 4 的字符串,最后一个 "I" 表示最后紧跟一个 unsigned int ,所以上面的打印 b 输出结果是:(12, 34, ‘abc', 56),完整的 Python pack 操作支持的数据类型见下表。

如果想传入多个而且数量可变的参数,可以采用先将变量放入tuple中,再传给pack

args = ("H""ello world "5)

struct.pack("c12si"*args)

# 等价于

struct.pack("c12si""H""ello world "5)

 

 

 

计算字节大小

可以利用 calcsize 来计算模式 “2I3sI” 占用的字节数

1

print struct.calcsize("2I3sI") # 16

可以看到上面的三个整型加一个 3 字符的字符串一共占用了 16 个字节。为什么会是 16 个字节呢?不应该是 15 个字节吗?1 个 int 4 字节,3 个字符 3 字节。但是在 struct 的打包过程中,根据特定类型的要求,必须进行字节对齐(关于字节对齐详见 https://en.wikipedia.org/wiki/Data_structure_alignment) 。由于默认 unsigned int 型占用四个字节,因此要在字符串的位置进行4字节对齐,因此即使是 3 个字符的字符串也要占用 4 个字节。

再看一下不需要字节对齐的模式

1

print struct.calcsize("2Is") # 9

由于单字符出现在两个整型之后,不需要进行字节对齐,所以输出结果是 9。

unpack 操作

对于 unpack 而言,只要 fmt 对应的字节数和字节字符串 string 的字节数一致,就可以成功的进行解析,否则 unpack 函数将抛出异常。例如我们也可以使用如下的 fmt 解析出 a :

1

2

3

c = struct.unpack("2I2sI", a)

print struct.calcsize("2I2sI")

print # 16 (12, 34, 'ab', 56)

不定长数据 pack

如果打包的数据长度未知该如何打包,这样的打包在网络传输中非常常见。处理这种不定长的内容的主要思路是把长度和内容一起打包,解包时首先解析内容的长度,然后再读取正文。

打包变长字符串

对于变长字符在处理的时候可以把字符的长度当成数据的内容一起打包。

1

2

s = bytes(s)

data = struct.pack("I%ds" % (len(s),), len(s), s)

上面代码把字符 s 的长度打包成内容,可以在进行内容读取的时候直接读取。

解包变长字符串

1

2

int_size = struct.calcsize("I")

(i,), data = struct.unpack("I", data[:int_size]), data[int_size:]

解包变长字符时首先解包内容的长度,在根据内容的长度解包数据

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

Character   Byte order  Size and alignment

@   native  native            凑够4个字节

=   native  standard        按原字节数

<   little-endian   standard        按原字节数

>   big-endian  standard       按原字节数

!   network (= big-endian)  

standard       按原字节数

使用方法是放在fmt的第一个位置,就像’@5s6sif’


 

  • 7
    点赞
  • 42
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值