В Python говорится, что мне нужны 4 байта для кода формата "BH":
struct.error: unpack requires a string argument of length 4
Вот код, я включаю 3 байта, как я думаю, необходим:
major, minor = struct.unpack("BH", self.fp.read(3))
"B" Неподписанный символ (1 байт) + "H" Короткое целое без знака (2 байта) = 3 байта (!?)
struct.calcsize ("BH") говорит 4 байта.
Править: Файл составляет ~800 МБ, и это находится в первых нескольких байтах файла, таким образом, я вполне уверен, что существуют данные, оставленные быть считанными.
Модуль структуры имитирует структуры C. Процессору требуется больше циклов ЦП, чтобы прочитать 16-битное слово по нечетному адресу или 32-битное двойное слово по адресу, не делящемуся на 4, поэтому структуры добавляют «байты заполнения», чтобы элементы структуры попадали на естественные границы. Примите во внимание:
struct { 11
char a; 012345678901
short b; ------------
char c; axbbcxxxdddd
int d;
};
Эта структура будет занимать 12 байтов памяти (x - байты заполнения).
Python работает аналогично (см. Документацию struct ):
>>> import struct
>>> struct.pack('BHBL',1,2,3,4)
'\x01\x00\x02\x00\x03\x00\x00\x00\x04\x00\x00\x00'
>>> struct.calcsize('BHBL')
12
Компиляторы обычно имеют способ устранения заполнения. В Python любое из = <>! устранит заполнение:
>>> struct.calcsize('=BHBL')
8
>>> struct.pack('=BHBL',1,2,3,4)
'\x01\x02\x00\x03\x04\x00\x00\x00'
Остерегайтесь позволять структуре обрабатывать заполнение. В C эти структуры:
struct A { struct B {
short a; int a;
char b; char b;
}; };
обычно имеют размер 4 и 8 байтов соответственно. Заполнение происходит в конце структуры, если структуры используются в массиве. Это позволяет членам «a» выровняться по правильным границам для структур, которые будут позже в массиве. Модуль структуры Python не заполняется в конце:
>>> struct.pack('LB',1,2)
'\x01\x00\x00\x00\x02'
>>> struct.pack('LBLB',1,2,3,4)
'\x01\x00\x00\x00\x02\x00\x00\x00\x03\x00\x00\x00\x04'
По умолчанию на многих платформах короткий будет выровнен по смещению, кратному 2, поэтому после символа будет добавлен байт заполнения.
Чтобы отключить это, используйте: struct.unpack ("= BH", data)
. Это будет использовать стандартное выравнивание, которое не добавляет отступов:
>>> struct.calcsize('=BH')
3
Символ =
будет использовать собственный порядок байтов. Вы также можете использовать <
или >
вместо =
для принудительного порядка байтов с прямым или обратным порядком байтов соответственно.