使用kaitai struct& amp解析二进制消息蟒蛇

时间:2018-04-06 19:28:33

标签: python kaitai-struct

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

对于适合内存的小型日志文件,如何让msg_log.py检查日志中的第2,第3和后续消息?

对于非常大的日志文件,我希望通过字节缓冲区来分页输入。我还没有做到这一点,并没有找到关于如何去做的例子或讨论。当内容发生变化时,如何使msg_log.py与分页字节缓冲区保持同步?

我的消息结构目前定义如下。 (我还使用了" seq"而不是"实例",但仍然只能检查第一条消息。)

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 个答案:

答案 0 :(得分:0)

从单个流中解析连续多个结构可以通过以下方式实现:

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 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