struct.error: распакуйте требует аргумента строки длины 4

В 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 МБ, и это находится в первых нескольких байтах файла, таким образом, я вполне уверен, что существуют данные, оставленные быть считанными.

21
задан Thomas O 10 April 2010 в 01:12
поделиться

2 ответа

Модуль структуры имитирует структуры 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'
22
ответ дан 29 November 2019 в 21:24
поделиться

По умолчанию на многих платформах короткий будет выровнен по смещению, кратному 2, поэтому после символа будет добавлен байт заполнения.

Чтобы отключить это, используйте: struct.unpack ("= BH", data) . Это будет использовать стандартное выравнивание, которое не добавляет отступов:

>>> struct.calcsize('=BH')
3

Символ = будет использовать собственный порядок байтов. Вы также можете использовать < или > вместо = для принудительного порядка байтов с прямым или обратным порядком байтов соответственно.

8
ответ дан 29 November 2019 в 21:24
поделиться
Другие вопросы по тегам:

Похожие вопросы: