我正在尝试按照此处的示例处理二进制格式:
http://dabeaz.blogspot.jp/2009/08/python-binary-io-handling.html
>>> from ctypes import *
>>> class Point(Structure):
>>> _fields_ = [ ('x',c_double), ('y',c_double), ('z',c_double) ]
>>>
>>> g = open("foo","rb") # point structure data
>>> q = Point()
>>> g.readinto(q)
24
>>> q.x
2.0
我已经定义了标题的结构,并且正在尝试将数据读入我的结构中,但是遇到了一些困难。我的结构是这样的:
class BinaryHeader(BigEndianStructure):
_fields_ = [
("sequence_number_4bytes", c_uint),
("ascii_text_32bytes", c_char),
("timestamp_4bytes", c_uint),
("more_funky_numbers_7bytes", c_uint, 56),
("some_flags_1byte", c_byte),
("other_flags_1byte", c_byte),
("payload_length_2bytes", c_ushort),
]
对于像 c_int 这样的整数类型字段,可以给出第三个可选项。它必须是一个小的正整数,定义字段的位宽。
因此,("more_funky_numbers_7bytes", c_uint, 56),
我尝试将该字段定义为 7 字节字段,但出现错误:
ValueError:位域无效的位数
所以我的第一个问题是如何定义一个 7 字节的 int 字段?
然后,如果我跳过该问题并注释掉“more_funky_numbers_7bytes”字段,则结果数据将被加载..但正如预期的那样,只有 1 个字符被加载到“ascii_text_32bytes”中。出于某种原因16
,我假设返回的是它读入结构的计算字节数......但是如果我注释掉我的“时髦数字”字段并且“”ascii_text_32bytes”只给出一个字符(1个字节),那不应该是13,而不是16吗???
然后我尝试将 char 字段分解为一个单独的结构,并从我的 Header 结构中引用它。但这也不起作用......
class StupidStaticCharField(BigEndianStructure):
_fields_ = [
("ascii_text_1", c_byte),
("ascii_text_2", c_byte),
("ascii_text_3", c_byte),
("ascii_text_4", c_byte),
("ascii_text_5", c_byte),
("ascii_text_6", c_byte),
("ascii_text_7", c_byte),
("ascii_text_8", c_byte),
("ascii_text_9", c_byte),
("ascii_text_10", c_byte),
("ascii_text_11", c_byte),
.
.
.
]
class BinaryHeader(BigEndianStructure):
_fields_ = [
("sequence_number_4bytes", c_uint),
("ascii_text_32bytes", StupidStaticCharField),
("timestamp_4bytes", c_uint),
#("more_funky_numbers_7bytes", c_uint, 56),
("some_flags_1byte", c_ushort),
("other_flags_1byte", c_ushort),
("payload_length_2bytes", c_ushort),
]
所以,任何想法如何:
- 定义一个 7 字节字段(我需要使用定义的函数对其进行解码)
- 定义一个 32 字节的静态 char 字段
更新
我找到了一个似乎有效的结构......
class BinaryHeader(BigEndianStructure):
_fields_ = [
("sequence_number_4bytes", c_uint),
("ascii_text_32bytes", c_char * 32),
("timestamp_4bytes", c_uint),
("more_funky_numbers_7bytes", c_byte * 7),
("some_flags_1byte", c_byte),
("other_flags_1byte", c_byte),
("payload_length_2bytes", c_ushort),
]
但是,现在我剩下的问题是,为什么使用时.readinto()
:
f = open(binaryfile, "rb")
mystruct = BinaryHeader()
f.readinto(mystruct)
它正在返回52
,而不是预期的,51
. 额外的字节从何而来,又去往何方?
更新 2
对于那些感兴趣的人,这里有一个将值读入 eryksun 提到的命名元组的替代方法的示例:struct
>>> record = 'raymond \x32\x12\x08\x01\x08'
>>> name, serialnum, school, gradelevel = unpack('<10sHHb', record)
>>> from collections import namedtuple
>>> Student = namedtuple('Student', 'name serialnum school gradelevel')
>>> Student._make(unpack('<10sHHb', record))
Student(name='raymond ', serialnum=4658, school=264, gradelevel=8)