【问题标题】:Reading Structure Binary Data in Python?在 Python 中读取结构二进制数据?
【发布时间】:2011-05-25 23:12:28
【问题描述】:

有没有像 Ruby 的 BinData 这样的优秀 Python 解决方案来读取用户定义的二进制文件/流格式?如果不是,那么在 Python 中除了使用 struct 模块之外,首选的方法是什么?

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

最好以这样一种方式定义不同的记录类型及其结构,以便我可以简单地将二进制 blob 传递给某物,然后由它处理其余部分(对象生成等)。简而言之,您定义的模板/映射如何解释二进制数据。

【问题讨论】:

  • 看过struct 模块吗?
  • 是的,但乍一看我不知道有一种方法可以指定像 BinData 这样的自定义结构。
  • 你需要做哪些struct模块不能做的事情?
  • “自定义结构”是什么意思?您需要比“像 [Ruby's] binData”更具体。通过提供非常模糊的要求,您不必要地限制了可能能够帮助您的人数。能够回答您问题的人是那些在 Ruby 和 Python 中阅读二进制数据的经验丰富的人。这是一个非常小的人口。即使是拥有良好 Ruby 和 Python 经验的开发人员也很少,更不用说处理原始二进制数据(当今世界越来越少见)。
  • 感谢尼古拉斯。现在阅读它,我意识到我匆忙发布了这个问题,并没有花时间解释我实际上想要做什么。我已经更新了我上面的问题。

标签: python ruby binary binary-data


【解决方案1】:

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

【讨论】:

    【解决方案2】:

    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

    【讨论】:

      【解决方案3】:

      struct 模块可能会起作用,但您也可以将 python 绑定用于 Google 的 protocol buffers

      【讨论】:

        【解决方案4】:

        我想举一个例子来说明如何在 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

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2017-07-10
          • 2022-01-11
          • 1970-01-01
          • 2010-12-08
          • 1970-01-01
          • 2011-03-14
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多