web-dev-qa-db-fra.com

struct.error: décompresser nécessite un argument de chaîne de longueur 4

Python dit que j'ai besoin de 4 octets pour un code de format "BH":

struct.error: unpack requires a string argument of length 4

Voici le code, je mets en 3 octets car je pense que c'est nécessaire:

major, minor = struct.unpack("BH", self.fp.read(3))

"B" Caractère non signé (1 octet) + "H" Non signé court (2 octets) = 3 octets (!?)

struct.calcsize ("BH") indique 4 octets.

EDIT: Le fichier est ~ 800 Mo et c'est dans les premiers octets du fichier, donc je suis assez certain qu'il reste des données à lire.

21
Thomas O

Le module struct imite les structures C. Il faut plus de cycles CPU pour qu'un processeur lise un mot 16 bits sur une adresse impaire ou un mot 32 bits sur une adresse non divisible par 4, donc les structures ajoutent des "octets de remplissage" pour faire tomber les membres de la structure sur des limites naturelles. Considérer:

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

Cette structure occupera 12 octets de mémoire (x étant des octets de pavé).

Python fonctionne de manière similaire (voir la documentation 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

Les compilateurs ont généralement un moyen d'éliminer le rembourrage. En Python, l'un des = <>! éliminera le rembourrage:

>>> struct.calcsize('=BHBL')
8
>>> struct.pack('=BHBL',1,2,3,4)
'\x01\x02\x00\x03\x04\x00\x00\x00'

Méfiez-vous de laisser struct gérer le rembourrage. En C, ces structures:

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

sont généralement de 4 et 8 octets, respectivement. Le remplissage se produit à la fin de la structure dans le cas où les structures sont utilisées dans un tableau. Cela maintient les membres "a" alignés sur des limites correctes pour les structures plus tard dans le tableau. Le module struct de Python ne remplit pas à la fin:

>>> 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
Mark Tolonen

Par défaut, sur de nombreuses plateformes, le short sera aligné sur un décalage à un multiple de 2, donc un octet de remplissage sera ajouté après le caractère.

Pour désactiver cela, utilisez: struct.unpack("=BH", data). Cela utilisera l'alignement standard, qui n'ajoute pas de remplissage:

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

Le = le caractère utilisera l'ordre des octets natif. Vous pouvez aussi utiliser < ou > au lieu de = pour forcer l'ordre des octets petit-boutien ou grand-boutien, respectivement.

8
interjay