Tôi đang cố gắng để xử lý một định dạng nhị phân, làm theo tấm gương ở đây:dữ liệu nhị phân Parsing vào đối tượng ctypes Cấu trúc qua readinto()
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
tôi đã xác định một cấu trúc header của tôi và tôi đang cố gắng đọc dữ liệu vào cấu trúc của mình, nhưng tôi đang gặp một số khó khăn. cấu trúc của tôi là như thế này:
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ác ctypes documentation nói:
For integer type fields like c_int, a third optional item can be given. It must be a small positive integer defining the bit width of the field.
Vì vậy, đối ("more_funky_numbers_7bytes", c_uint, 56),
Tôi đã cố gắng để xác định lĩnh vực này như một lĩnh vực 7 byte, nhưng tôi nhận được lỗi:
ValueError: number of bits invalid for bit field
Vì vậy, vấn đề đầu tiên của tôi là làm cách nào để xác định trường int 7 byte?
Sau đó, nếu tôi bỏ qua vấn đề đó và nhận xét trường "more_funky_numbers_7bytes", dữ liệu kết quả sẽ được tải trong .. nhưng như dự kiến chỉ có 1 ký tự được tải vào "ascii_text_32bytes". Và vì lý do nào đó trả về 16
mà tôi giả định là số byte được tính toán mà nó đọc vào cấu trúc ... nhưng nếu tôi nhận xét trường "số sôi nổi" của tôi và "" ascii_text_32bytes "chỉ cho một char (1 byte) , không nên mà là 13, không phải 16 ???
Sau đó, tôi đã cố gắng phá vỡ lĩnh vực char thành một cấu trúc riêng biệt, và tham chiếu từ bên trong cấu trúc header của tôi. Nhưng điều đó không làm việc hoặc ...
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),
]
Vì vậy, bất kỳ ý tưởng làm thế nào để:
- Xác định một lĩnh vực 7 byte (mà I'l Tôi cần để giải mã sử dụng một chức năng được xác định)
- Xác định một lĩnh vực char tĩnh của 32 byte
CẬP NHẬT
Tôi đã tìm thấy một cấu trúc mà dường như làm việc ...
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),
]
Bây giờ, câu hỏi còn lại của tôi là, tại sao khi sử dụng .readinto()
:
f = open(binaryfile, "rb")
mystruct = BinaryHeader()
f.readinto(mystruct)
Máy quay trả lại 52
và không phải là mong đợi, 51
. Đâu là byte phụ đến từ đâu, và nó đi đâu?
UPDATE 2 Đối với những người quan tâm đây là một example của một struct
phương pháp khác để đọc các giá trị vào một namedtuple đề cập bởi eryksun:
>>> 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)
Nếu bạn nhìn vào tệp nhị phân của mình bằng một số Hex Editor, bạn có thấy 51 byte không? Ngoài ra, 'len (mystruct) 'nói gì? –
Có, 'binaryfile' là hơn 50KB. 'len (mystruct)' dường như không hoạt động, nhưng 'sizeof (mystruct)' trả về 52 ... – monkut
Bạn có thể thêm '_pack_ = 1' vào định nghĩa, nhưng hãy xem xét sử dụng mô-đun' struct' với ' được đặt tên thay thế. – eryksun