代码之家  ›  专栏  ›  技术社区  ›  Thomas O

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

  •  20
  • Thomas O  · 技术社区  · 14 年前

    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字节(!?)

    结构calcsize(“BH”)表示4个字节。

    编辑:该文件是约800 MB,这是在文件的头几个字节,所以我相当肯定有数据留下来读取。

    2 回复  |  直到 14 年前
        1
  •  27
  •   Mark Tolonen    14 年前

    struct模块模仿C结构。处理器读取奇数地址上的16位字或不能被4整除的地址上的32位dword需要更多的CPU周期,因此结构添加“pad bytes”使结构成员落在自然边界上。考虑:

    struct {                   11
        char a;      012345678901
        short b;     ------------
        char c;      axbbcxxxdddd
        int d;
    };
    

    这个结构将占用12个字节的内存(x是pad字节)。

    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 A {       struct B {
        short a;         int a;
        char b;          char b;
    };               };
    

    通常分别为4字节和8字节。填充发生在结构的末尾,以防在数组中使用这些结构。这将使“a”成员在数组后面的结构的正确边界上保持对齐。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'
    
        2
  •  8
  •   interjay    14 年前

    默认情况下,在许多平台上,short将以2的倍数与偏移量对齐,因此在char后面会添加一个填充字节。

    要禁用此功能,请使用: struct.unpack("=BH", data) . 这将使用标准对齐方式,不添加填充:

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

    = 字符将使用本机字节排序。你也可以使用 < > 而不是 = 分别强制小端字节或大端字节排序。