Python二进制数据结构Struct的具体使用

作者:一天一篇Python库 时间:2022-07-10 00:01:59 

二进制数据结构Struct

在C/C++语言中,struct被称为结构体。而在Python中,struct是一个专门的库,用于处理字节串与原生Python数据结构类型之间的转换。

本篇,将详细介绍二进制数据结构struct的使用方式。

函数与Struct类

struct库包含了一组处理结构值得模块级函数,以及一个Struct类。格式指示符将由字符串格式转换为一种编译表示,这与处理正则表达式得方式类似。

这个转换会耗费一些资源,所以创建一个Struct实例并再这个实例上调用方法时,只完成一次转换,往往会更高效。

打包

Struct支持使用格式指示符将数据打包为字符串,另外支持从字符串解包数据,格式指示符由表示数据类型的字符串和可选的数量及字节序指示符构成。

下面,我们来打包一个元组,将其转换为16进制字节序列,示例如下:


import struct
import binascii

values = (2, 'lyj'.encode('UTF-8'), 3.8)
s = struct.Struct('I 3s f')
packed_data = s.pack(*values)
print("原值:", values)
print("格式指示符:", s.format)
print("大小:", s.size, 'bytes')
print("打包值:", binascii.hexlify(packed_data))

运行之后,效果如下:

Python二进制数据结构Struct的具体使用

这里的格式指示符为“I 3s f”。前面介绍array数组时,我们已经列出过一个表格。其中I标识一个整型或长整型,3s表示3个字节字符串(lyj),f表示浮点数。

解包

struct库使用unpack()可以从打包的表示数据中抽取数据,这里直接复制上面的打包值,进行测试。示例如下:


import struct
import binascii

packed_data = binascii.unhexlify(b'020000006c796a0033337340')
s = struct.Struct('I 3s f')
unpacked_data = s.unpack(packed_data)
print("解包值:", unpacked_data)

运行之后,效果如下:

Python二进制数据结构Struct的具体使用

虽然使用unpack()解包基本会得到相同值,但浮点数的值有微小的差别。

字节序指示符

默认情况下,值会使用原生C库的字节序(endianness)来编码。Struct的字节序指示符如下表所示:

代码含义
@原生顺序
=原生标准
<小端
>大端
!网络顺序

示例如下:


import struct
import binascii

values = (2, 'lyj'.encode('UTF-8'), 3.8)
endianness = [
   ('@', '原生顺序'),
   ('=', '原生标准'),
   ('<', '小端'),
   ('>', '大端'),
   ('!', '网络顺序'),
]
for code, name in endianness:
   s = struct.Struct(code + ' I 3s f')
   packed_data = s.pack(*values)
   print("格式化字符串:", s.format, ' for ', name)
   print("大小:", s.size, 'bytes')
   print("打包:", binascii.hexlify(packed_data))
   print("解包:", s.unpack(packed_data))

运行之后,效果如下:

Python二进制数据结构Struct的具体使用

如果想改变字节序来编码,如上面代码所示,只需要改变格式串中提供一个显式的字节序指令,就可以很容易地覆盖这个默认选择。

缓冲区

通常在强调性能的情况下或者向扩展模块传入或传出数据时才会处理二进制打包数据。

为了避免为每个打包结构分配一个新缓冲区所带来的开销,通常情况下,我们使用pack_into()和unpack_from()方法支持直接写入预分配的缓冲区。

示例如下:


import struct
import binascii
import ctypes
import array

values = (2, 'lyj'.encode('UTF-8'), 3.8)
s = struct.Struct('I 3s f')
print("原始值:", values)
b = ctypes.create_string_buffer(s.size)
print("打包之前(缓冲区的值):", binascii.hexlify(b.raw))
s.pack_into(b, 0, *values)
print("打包之后(缓冲区的值):", binascii.hexlify(b.raw))
print("解包:", s.unpack_from(b, 0))

a = array.array('b', b'\0' * s.size)
print("打包之前(缓冲区的值):", binascii.hexlify(a))
s.pack_into(a, 0, *values)
print('打包之后(缓冲区的值):', binascii.hexlify(a))
print("解包:", s.unpack_from(a, 0))

运行之后,效果如下:

Python二进制数据结构Struct的具体使用

这里通过两种方式,创建缓冲区。其中size属性用于指出缓冲区需要的大小。

来源:https://liyuanjinglyj.blog.csdn.net/article/details/115861919

标签:Python,二进制数据结构,Struct
0
投稿

猜你喜欢

  • 一文学会使用OpenCV构建文档扫描仪

    2023-08-02 12:35:05
  • 从零开始学习Node.js系列教程二:文本提交与显示方法

    2024-05-08 09:35:30
  • python实现连接mongodb的方法

    2022-10-18 08:34:18
  • python3.6实现学生信息管理系统

    2021-02-09 20:54:48
  • Python实现位图分割的效果

    2021-09-05 11:13:15
  • 实例演练ASP+XML编程

    2007-10-11 13:53:00
  • citespace数据处理:用python对Ref文档进行去重方式

    2022-07-06 06:01:13
  • 详解django的serializer序列化model几种方法

    2022-12-06 00:40:08
  • SQL Server性能的改进得益于逻辑数据库设计

    2009-10-23 13:55:00
  • Layui表格监听行单双击事件讲解

    2024-04-19 10:45:00
  • python标准算法实现数组全排列的方法

    2022-03-18 15:11:38
  • Oracle Session每日统计功能实现

    2023-07-22 09:47:24
  • 再论Javascript的类继承

    2010-06-26 12:48:00
  • 浅谈function(函数)中的动态参数

    2023-08-11 10:23:59
  • python 利用turtle模块画出没有角的方格

    2022-03-09 04:25:04
  • JSONObject.toString

    2008-03-09 19:12:00
  • 土豆网前端概况

    2008-01-24 12:06:00
  • Python选课系统开发程序

    2023-07-21 00:25:03
  • Django实现跨域的2种方法

    2021-11-27 00:15:42
  • Python教程之类型转换详解

    2021-03-23 02:48:17
  • asp之家 网络编程 m.aspxhome.com