在Python中读取结构化二进制数据?

4

是否有像Ruby的BinData一样好用的Python解决方案,可以读取用户定义的二进制文件/流格式?如果没有,那么除了使用struct模块之外,在Python中完成这项任务的首选方法是什么?

我有一个存储“事件记录”的二进制文件。记录的大小是动态的,因此我必须读取每个记录的前几个字节以确定记录的长度和记录类型。不同的记录类型将具有不同的字节布局。例如,类型为“警告”的记录可能包含三个4字节int,后跟一个128字节值,而类型为“信息”的记录可能只有五个4字节int。

定义不同的记录类型及其结构的方式最好是这样的:我只需将二进制数据块传递给某个东西,它就可以处理剩下的事情(对象生成等)。简而言之,您正在定义如何解释二进制数据的模板/映射。


2
你曾经看过struct模块吗? - Santa
是的,但乍一看我不知道有没有办法指定自定义结构,比如BinData。 - dj29
1
结构体模块无法完成哪些任务? - Keith
你所说的“自定义结构”是什么意思?你需要比“像[Ruby的] binData”更具体。通过提供非常模糊的要求,你在不必要地限制了可能能够帮助你的人数。能够回答你问题的人是那些在Ruby和Python中都有大量读取二进制数据经验的人。这是一个非常小的人群。即使是具有良好的Ruby和Python经验的开发人员的集合也相当小,更不用说处理原始二进制数据(在今天的世界中越来越少见了)。 - Nicholas Knight
谢谢你的回复,Nicholas。我现在正在阅读它,意识到我匆忙发布了这个问题,并没有花时间解释我实际想做什么。我已经更新了我的问题。 - dj29
4个回答

4

也许您正在寻找一个纯Python 2和3二进制解析库?您可以尝试 Construct


3

Python的struct模块工作方式如下:

record_header = struct.Struct("<cb") 
warning = struct.Struct("<iii128")
info = struct.Struct("<iiiii")

while True:
    header_text = input.read(record_header.size)
    # file is empty
    if not header_text:
       break
    packet_type, extra_data = record_header.unpack(header_text)
    if packet_type == 'w':
        warning_data = warning.unpack( input.read(warning.size) )
    elif packet_type == 'i':
        info_data = info.unpack( input.read(info.size) )

请查看文档以获取详细信息:http://docs.python.org/library/struct.html

2

结构体模块可能会起作用,但您也可以使用Google的协议缓冲区的Python绑定。


-1
我想举个例子来说明如何在Python中进行读取。
typedef struct {
    ID             chunkname;
    long           chunksize;

    /* Note: there may be additional fields here, depending upon your data. */

} Chunk;

如何在Python中从文件中读取结构数据?这里有一种方法:

class Chunk:
def __init__(self, file, align=True, bigendian=True, inclheader=False):
    import struct
    self.closed = False
    self.align = align      # whether to align to word (2-byte) boundaries
    if bigendian:
        strflag = '>'
    else:
        strflag = '<'
    self.file = file
    self.chunkname = file.read(4)
    if len(self.chunkname) < 4:
        # you need to take care of end of file
        raise EOFError
    try:
        # you could use unpack
        # http://docs.python.org/2/library/struct.html#format-characters
        # here 'L' means 'unsigned long' 4 standard size
        self.chunksize = struct.unpack(strflag+'L', file.read(4))[0]
    except struct.error:
        # you need to take care of end of file
        raise EOFError
    if inclheader:
        self.chunksize = self.chunksize - 8 # subtract header
    self.size_read = 0
    try:
        self.offset = self.file.tell()
    except (AttributeError, IOError):
        self.seekable = False
    else:
        self.seekable = True

所以你需要理解C结构体和struct.unpack()格式之间的映射关系http://docs.python.org/2/library/struct.html#format-characters


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