使用Kaitai Struct和Python解析二进制消息

3

我需要从非常大的消息日志中提取和处理数据(可变大小的二进制消息)。使用Gif示例和在线文档,我已经定义并编译了可变大小消息布局到msg_log.py。调用msg_log.from_file("small_logfile")让我能够检查并验证日志文件中第一条消息的字段值。

对于适合内存的小型日志文件,我如何使msg_log.py检查日志文件中的第二、第三或后续消息?

对于非常大的日志文件,我希望通过一个字节缓冲区分页输入。目前我还没有做这个操作,并且没有找到关于如何进行此操作的示例或讨论。当内容发生变化时,我该如何使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
1个回答

3
从单个流中连续解析多个结构可以通过以下方式实现:
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()

我不确定你所说的“分页浏览字节缓冲区”的含义。上述方法本身并不会将整个文件加载到内存中,而是按照请求使用类似于read()的普通调用进行读取。
如果您想要更好的性能,并且您处理的是一个固定大小的大文件,您可以选择进行内存映射。这样,您只使用了一块内存区域,操作系统会负责将文件的相关部分加载到实际物理内存中所需的输入/输出。对于Python,有一个运行时PR实现了辅助功能,或者您可以自己执行以下操作:
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

美妙。这使得从二进制文件中提取可变大小的对象就像从文本文件中读取一行文本一样容易。 - new-python-user
嗯,有点。如果这回答了问题,请考虑将其标记为“接受的答案”。 - GreyCat

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接