struct.error:解包需要长度为4的字符串参数

27 投票
2 回答
113073 浏览
提问于 2025-04-15 21:26

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个字节。

补充说明:这个文件大约有800MB,而这段代码是在文件的前几个字节,所以我很确定还有数据可以读取。

2 个回答

8

在很多平台上,默认情况下,短整型(short)会被对齐到2的倍数,这样在字符后面就会多出一个填充字节。

如果你想关闭这个功能,可以使用:struct.unpack("=BH", data)。这样就会使用标准对齐方式,不会添加填充字节:

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

这里的=表示使用本地的字节顺序。你也可以用<或者>来强制使用小端字节顺序或大端字节顺序。

28

struct模块的作用是模拟C语言中的结构体。处理器在读取某些特定地址的数据时会比较慢,比如在奇数地址读取16位的数据,或者在不能被4整除的地址读取32位的数据。因此,为了让结构体的成员在合适的边界上,结构体会添加一些“填充字节”。举个例子:

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'

要小心让struct处理填充字节。在C语言中,这些结构体:

struct A {       struct B {
    short a;         int a;
    char b;          char b;
};               };

通常分别占用4个和8个字节。填充字节通常出现在结构体的末尾,以便这些结构体在数组中使用时能够保持对齐。这样可以确保数组中后面的结构体的成员也能在正确的边界上对齐。而Python的struct模块在末尾并不会添加填充:

>>> 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'

撰写回答