最近接到一个小需求,解读消息服务器的消息日志,因为消息服务器记录消息使用的是二进制方式记录到文件中,需要解析出来并转换为人能看的字符.由于对性能没什么要求,所以选定用python作为主要开发语言,开发一个转换的小工具.这里要用到python的struct模块
消息的格式用结构体描述如下:
struct { uint64_t time; int32_t datalen; vecter<char> protobuf; }
protobuf还需要使用python protobuf进行进一步的解析.
大体处理流程:
1 打开读取二进制文件
2 打开转换后的文件
3 按照结构读取二进制文件
4 每解析一个结构,再解析一次protobuf,将数据还原
5 将一条完整消息追加写入到转换后的文件中
6 重复3-5步直到文件结束
需要说明:
文件的打开
FileObject = open(SrcFile, "rb")
文件的关闭
FileObject.close()
文件的读取
FileObject.read()
文件的写入
FileObject.write()
struct模块操作:
struct模块中最重要的三个函数是:
pack():打包结构图
unpack():解析结构体
calcsize():计算结构体占用的字节数
其中fmt,有一个官方的对照表:
| Format | C Type | Python | 字节数 |
|---|---|---|---|
| x | pad byte | no value | 1 |
| c | char | string of length 1 | 1 |
| b | signedchar | integer | 1 |
| B | unsignedchar | integer | 1 |
| ? | _Bool | bool | 1 |
| h | short | integer | 2 |
| H | unsignedshort | integer | 2 |
| i | int | integer | 4 |
| I | unsignedint | integer or long | 4 |
| l | long | integer | 4 |
| L | unsignedlong | long | 4 |
| q | longlong | long | 8 |
| Q | unsignedlonglong | long | 8 |
| f | float | float | 4 |
| d | double | float | 8 |
| s | char[] | string | 1 |
| p | char[] | string | 1 |
| P | void* | long |
fmt前缀修饰字符表
| @ | native | native 凑够4个字节 |
| = | native | standard 按原字节数 |
| < | little-endian | standard 按原字节数 |
| > | big-endian | standard 按原字节数 |
| ! | network (= big-endian) | standard 按原字节数 |
实现过程
将原有结构体拆分为
struct {
uint64_t time;
int32_t datalen;
} 和 string msg 读取
源码如下:
FileObj = open(ObjFile, "rb")
try:
while True:
BytesRead=FileObj.read(struct.calcsize("=QI"))
if not BytesRead:
break
msgtime, msglen = struct.unpack("=QI",BytesRead)
print "msgtime:",msgtime," msglen:",msglen,
ByteMsg=FileObj.read(msglen)
msgpb = BaseMessage_pb2.basemessage()
msgpb.ParseFromString(ByteMsg)
print " msg:",msgpb.mPayload
finally:
FileObj.close()
本文介绍如何使用Python解析特定格式的二进制消息日志,并将其转换为可读文本。涉及Python的struct模块和protobuf解析。
5万+

被折叠的 条评论
为什么被折叠?



