Python解析变长结构体
最近接到一个需求,需要使用 Python 解析 C 来的数据包,而数据包中的格式是通过如下结构体定义的:
typedef struct msg_t
{
int oid;
int msg_len;
char msg_data[0];
}MSG_T;
其中的 msg_data
字符串的长度是由 msg_len
给出的,因此需要首先解析出 msg_len
的数值,再读取 msg_len
的内容。
在 Python 中可以通过 struct 模块完成这一操作,针对以上数据结构的 python 解析代码如下:
OID = 0
msgLen = 0
msgData = ""
sFormat = ""
OID, msgLen = struct.unpack('II', syncMsg[0:8])
sFormat = 'II' + str(msgLen) + 's'
OID, msgLen, msgData = struct.unpack(sFormat, syncMsg)
msgData = msgData.decode()
#print("OID: ", OID, "nMsgLen: ", msgLen, "nMsgData: ", msgData.decode())
代码最核心之处在于 unpack
时的单引号部分,其中 I
代表 Int
, 128s
则代表长度为 128 的字符串。在这里首先解析长度,再拼接处数据格式,进而解析。
struct 中支持的格式如下表:
Format |
C Type |
Python |
字节数 |
---|---|---|---|
x |
pad byte |
no value |
1 |
c |
char |
string of length 1 |
1 |
b |
signed char |
integer |
1 |
B |
unsigned char |
integer |
1 |
? |
_Bool |
bool |
1 |
h |
short |
integer |
2 |
H |
unsigned short |
integer |
2 |
i |
int |
integer |
4 |
I (大写的 i) |
unsigned int |
integer or long |
4 |
l (小写的 L) |
long |
integer |
4 |
L |
unsigned long |
long |
4 |
q |
long long |
long |
8 |
Q |
unsigned long long |
long |
8 |
f |
float |
float |
4 |
d |
double |
float |
8 |
s |
char[] |
string |
1 |
p |
char[] |
string |
1 |
P |
void * |
long |
4 |
参考文献
- 浅析Python中的struct模块: https://www.cnblogs.com/coser/archive/2011/12/17/2291160.html
- python struct 结构体: https://blog.csdn.net/CLinuxF/article/details/102478001
- Python中对字节流/二进制流的操作:struct模块简易使用教程: https://www.jianshu.com/p/5a985f29fa81
- struct --- 将字节串解读为打包的二进制数据: https://docs.python.org/zh-cn/3/library/struct.html
--------------------- Author: Frytea Title: Python解析变长结构体 Link: https://blog.frytea.com/archives/453/ Copyright: This work by TL-Song is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License.
- 如何让所有实体类用相同名称的主键(很有力的问题,比如所有表实体主键都用ID)
- Codeforces 834D The Bakery【dp+线段树维护+lazy】
- memcached安装及.NET中的Memcached.ClientLibrary使用详解
- AtCoder Beginner Contest 069【A,水,B,水,C,数学,D,暴力】
- 2017"百度之星"程序设计大赛 - 资格赛【1001 Floyd求最小环 1002 歪解(并查集),1003 完全背包 1004 01背包 1005 打表找规律+卡特兰数】
- 洛谷 2634&&BZOJ 2152: 聪聪可可【点分治学习+超详细注释】
- 【经验总结】Java在ACM算法竞赛编程中易错点
- 【Java学习笔记之六】java三种循环(for,while,do......while)的使用方法及区别
- 类A是公共的,应在名为A.java的文件中声明错误
- 逆天通用水印支持Winform,WPF,Web,WP,Win10。支持位置选择(9个位置 ==》[X])
- 【Java学习笔记之七】java函数的语法规则总结
- BZOJ 3038: 上帝造题的七分钟2【线段树区间开方问题】
- BZOJ 3211: 花神游历各国【线段树区间开方问题】
- WP、Win10开发或者WPF开发时绘制自定义窗体~例如:一个手机
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法