Maison  >  Article  >  développement back-end  >  Introduction détaillée à l'utilisation par Python de struct pour traiter les binaires (utilisation du pack et du déballage)

Introduction détaillée à l'utilisation par Python de struct pour traiter les binaires (utilisation du pack et du déballage)

高洛峰
高洛峰original
2017-03-19 14:49:492119parcourir

Parfois, vous devez utiliser python pour traiter des données binaires, par exemple, lors de l'accès à des fichiers et à des opérations de socket. À ce stade, vous pouvez utiliser le module struct de python pour le compléter. c La structure dans le langage Les trois fonctions

les plus importantes

dans le module struct sont pack(), unpack(), calcsize. ()

pack(fmt, v1, v2, ...) Selon le format donné (fmt), regroupez les données dans une string (en fait un flux d'octets similaire à une structure c )

unpack(fmt, string) Analyse la chaîne du flux d'octets selon le format donné (fmt) et renvoie le tuple analysé

calcsize(fmt) Calculer comment combien d'octets de mémoire un certain format (fmt) occupe-t-il ?

Les formats pris en charge dans la structure sont les suivants :

Pourmat C Type Python Nombre d'octets

x pad octet sans valeur 1

c chaîne de caractères de longueur 1 1

b caractère signé entier 1

B caractère entier non signé 1

? _Bool bool 1

h entier court 2

H entier court non signé 2

i int entier 4

I non signé int int eger ou long 4

l long entier 4

L non signé long long 4

q long long long 8

Q non signé long long long 8

f float float 4

d double float 8

s char[] chaîne 1

p char[] chaîne 1

P void * long

Remarque 1. q et Q ne sont intéressants que lorsque la machine supporte le fonctionnement 64 bits

Remarque 2. Il peut y avoir un nombre avant chaque format pour indiquer le nombre

Note 3. Le format s représente une chaîne d'une certaine longueur, 4s représente une chaîne de longueur 4, mais p représente une chaîne pascale

La note 4.P est utilisée pour convertir un pointeur, Sa longueur est liée à la longueur du mot machine

Note 5. Le dernier peut être utilisé pour représenter des types de pointeurs, occupant 4 octets

Afin d'échanger des données avec le structure en c, nous devons également considérer Certains compilateurs c ou c utilisent l'alignement des octets, généralement 4 octets pour les systèmes 32 bits, donc la structure est convertie selon l'ordre des octets de la machine locale. Vous pouvez utiliser le premier caractère du format pour changer. l'alignement. .La définition est la suivante :

Ordre des octets des caractères Taille et alignement

@natif natif Compose 4 octets

= standard natif Selon le nombre original de octets

< standard petit-endien basé sur le nombre d'octets d'origine

> standard big-endien basé sur le nombre d'octets d'origine

 ! -endian)

standard Selon le nombre d'octets d'origine

est utilisé en le plaçant à la première position de fmt, tout comme '@5s6sif'

Exemple 1 :

La structure est la suivante :

struct Header
{
    unsigned short id;
    char[4] tag;
    unsigned int version;
    unsigned int count;
}

Les données de structure ci-dessus ont été reçues via socket.recv, qui est stocké dans la chaîne s. Vous pouvez maintenant les analyser. utilisez la fonction unpack() :

import struct
id, tag, version, count = struct.unpack("!H4s2I", s)

Ci-dessus Dans la chaîne de format, ! indique que nous devons utiliser l'ordre des octets du réseau pour l'analyse, car nos données sont reçues du réseau et sont dans l'ordre des octets du réseau lorsque transmis sur le réseau. Le H suivant représente un court id non signé, 4s représente une chaîne longue de 4 octets et 2I représente deux données de type int non signées

Il suffit de passer un décompression, et maintenant nos informations ont été. enregistré dans l'identifiant, la balise, la version et le nombre .

De même, vous pouvez également facilement regrouper les données locales au format struct :

ss = struct.pack("!H4s2I", id, tag, version, count);

La fonction pack convertit l'identifiant, la balise, la version, compte au format struct selon le format spécifié. Sans l'en-tête de structure, ss est maintenant une chaîne (en fait un flux d'octets similaire à une structure c), et cette chaîne peut être envoyée via socket.send(ss).

Exemple 2 :

import struct
a=12.34
#将a变为二进制
bytes=struct.pack('i',a)

À ce stade, bytes est une chaîne de caractères, et la chaîne est la même que le contenu de stockage binaire de a en octets.

Effectuez ensuite l'opération inverse et convertissez les octets de données binaires existants (en fait une chaîne) en type de données de python :

#Remarque, unpack renvoie un tuple !!

a,=struct.unpack('i',bytes)

S'il est composé de plusieurs données, cela peut ressembler à ceci :

a='hello'
b='world!'
c=2
d=45.123
bytes=struct.pack('5s6sif',a,b,c,d)

Les octets à cet instant sont des données sous forme binaire, qui peuvent être directement Écrire un fichier tel que binfile.write(bytes)

puis lisez-le quand nous en avons besoin, bytes=binfile.read()

再通过struct.unpack()解码成python变量:

a,b,c,d=struct.unpack('5s6sif',bytes)

’5s6sif’这个叫做fmt,就是格式化字符串,由数字加字符构成,5s表示占5个字符的字符串,2i,表示2个整数等等,下面是可用的字符及类型,ctype表示可以与python中的类型一一对应。

注意:二进制文件处理时会碰到的问题

我们使用处理二进制文件时,需要用如下方法:

binfile=open(filepath,'rb')    
#读二进制文件
binfile=open(filepath,'wb')   
#写二进制文件

那么和binfile=open(filepath,’r')的结果到底有何不同呢?

不同之处有两个地方:

第一,使用’r'的时候如果碰到’0x1A’,就会视为文件结束,这就是EOF。使用’rb’则不存在这个问题。即,如果你用二进制写入再用文本读出的话,如果其中存在’0X1A’,就只会读出文件的一部分。使用’rb’的时候会一直读到文件末尾。

第二,对于字符串x=’abc\ndef’,我们可用len(x)得到它的长度为7,\n我们称之为换行符,实际上是’0X0A’。当我们用’w'即文本方式写的时候,在windows平台上会自动将’0X0A’变成两个字符’0X0D’,’0X0A’,即文件长度实际上变成8.。当用’r'文本方式读取时,又自动的转换成原来的换行符。如果换成’wb’二进制方式来写的话,则会保持一个字符不变,读取时也是原样读取。所以如果用文本方式写入,用二进制方式读取的话,就要考虑这多出的一个字节了。’0X0D’又称回车符。linux下不会变。因为linux只使用’0X0A’来表示换行。

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn