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
4

1 回答 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
于 2018-04-07T23:53:54.190 回答