使用 kaitai 结构解析二进制消息 & python
Parsing binary messages with kaitai struct & python
我需要从非常大的消息日志中提取和处理数据(可变大小的二进制消息)。使用 Gif 示例和在线文档,我定义了可变大小的消息布局并将其编译为 msg_log.py。调用 msg_log.from_file("small_logfile") 使我能够检查和验证日志文件中第一条消息的字段值。
对于适合内存的小日志文件,如何msg_log.py检查日志中的第 2 条、第 3 条和后续消息?
对于非常大的日志文件,我希望通过字节缓冲区对输入进行分页。我还没有这样做,也没有找到关于如何去做的例子或讨论。如何在内容更改时使 msg_log.py 与分页字节缓冲区保持同步?
我的消息结构目前定义如下。 (我也使用 "seq" 而不是 "instances",但仍然只能检查第一条消息。)
meta:
id: message
endian: be
instances:
msg_header:
pos: 0x00
type: message_header
dom_header:
pos: 0x06
type: domain_header
body:
pos: 0x2b
size: msg_header.length - 43
types:
message_header:
seq:
- id: length
type: u1
<other fixed-size fields - 5 bytes>
domain_header:
seq:
<fixed-size fields - 37 bytes>
message_body:
seq:
- id: body
size-eos: true
从单个流中连续解析多个结构可以通过以下方式实现:
from msg_log import Message
from kaitaistruct import KaitaiStream
f = open("yourfile.bin", "rb")
stream = KaitaiStream(f)
obj1 = Message(stream)
obj2 = Message(stream)
obj3 = Message(stream)
# etc
stream.close()
我不确定 "paging through a byte buffer" 是什么意思。上面的方法本身不会将整个文件加载到内存中,它会根据请求使用正常的 read()
类调用来读取它。
如果您想要更好的性能,并且要处理固定大小的大文件,则可以选择进行内存映射。这样您将只使用一个内存区域,而 OS 将负责将文件的相关部分加载到实际物理内存中所需的 input/output。对于 Python,有一个 PR for runtime 实现了它的助手,或者,您可以自己做:
from kaitaistruct import KaitaiStream
import mmap
f = open("yourfile.bin", "rb")
with mmap.mmap(f.fileno(), 0, access=mmap.ACCESS_READ) as buf:
stream = KaitaiStream(BytesIO(buf))
obj1 = Message(stream)
obj2 = Message(stream)
obj3 = Message(stream)
# etc
我需要从非常大的消息日志中提取和处理数据(可变大小的二进制消息)。使用 Gif 示例和在线文档,我定义了可变大小的消息布局并将其编译为 msg_log.py。调用 msg_log.from_file("small_logfile") 使我能够检查和验证日志文件中第一条消息的字段值。
对于适合内存的小日志文件,如何msg_log.py检查日志中的第 2 条、第 3 条和后续消息?
对于非常大的日志文件,我希望通过字节缓冲区对输入进行分页。我还没有这样做,也没有找到关于如何去做的例子或讨论。如何在内容更改时使 msg_log.py 与分页字节缓冲区保持同步?
我的消息结构目前定义如下。 (我也使用 "seq" 而不是 "instances",但仍然只能检查第一条消息。)
meta:
id: message
endian: be
instances:
msg_header:
pos: 0x00
type: message_header
dom_header:
pos: 0x06
type: domain_header
body:
pos: 0x2b
size: msg_header.length - 43
types:
message_header:
seq:
- id: length
type: u1
<other fixed-size fields - 5 bytes>
domain_header:
seq:
<fixed-size fields - 37 bytes>
message_body:
seq:
- id: body
size-eos: true
从单个流中连续解析多个结构可以通过以下方式实现:
from msg_log import Message
from kaitaistruct import KaitaiStream
f = open("yourfile.bin", "rb")
stream = KaitaiStream(f)
obj1 = Message(stream)
obj2 = Message(stream)
obj3 = Message(stream)
# etc
stream.close()
我不确定 "paging through a byte buffer" 是什么意思。上面的方法本身不会将整个文件加载到内存中,它会根据请求使用正常的 read()
类调用来读取它。
如果您想要更好的性能,并且要处理固定大小的大文件,则可以选择进行内存映射。这样您将只使用一个内存区域,而 OS 将负责将文件的相关部分加载到实际物理内存中所需的 input/output。对于 Python,有一个 PR for runtime 实现了它的助手,或者,您可以自己做:
from kaitaistruct import KaitaiStream
import mmap
f = open("yourfile.bin", "rb")
with mmap.mmap(f.fileno(), 0, access=mmap.ACCESS_READ) as buf:
stream = KaitaiStream(BytesIO(buf))
obj1 = Message(stream)
obj2 = Message(stream)
obj3 = Message(stream)
# etc