web-dev-qa-db-fra.com

Python écriture binaire

J'utilise python 3 J'ai essayé d'écrire du binaire dans un fichier que j'utilise r + b.

for bit in binary:
    fileout.write(bit)

où binaire est une liste contenant des nombres. Comment écrire ceci dans un fichier en binaire?

Le fichier de fin doit ressembler à b 'x07\x08\x07 \

Merci

12
Alon

Lorsque vous ouvrez un fichier en mode binaire, vous travaillez essentiellement avec le type bytes . Ainsi, lorsque vous écrivez dans le fichier, vous devez passer un objet bytes et lorsque vous le lisez, vous obtenez un objet bytes. En revanche, lorsque vous ouvrez le fichier en mode texte, vous travaillez avec des objets str.

Donc, écrire "binaire", c'est vraiment écrire une chaîne d'octets:

with open(fileName, 'br+') as f:
    f.write(b'\x07\x08\x07')

Si vous avez des entiers réels que vous souhaitez écrire en tant que binaire, vous pouvez utiliser la fonction bytes pour convertir une séquence d'entiers en objet octets:

>>> lst = [7, 8, 7]
>>> bytes(lst)
b'\x07\x08\x07'

En combinant cela, vous pouvez écrire une séquence d'entiers sous forme d'octets dans un fichier ouvert en mode binaire.


Comme Hyperboreus l'a souligné dans les commentaires, bytes n'acceptera qu'une séquence de nombres qui tient réellement dans un octet, c'est-à-dire des nombres entre 0 et 255. Si vous voulez stocker des entiers arbitraires (positifs) de la manière dont ils sont , sans avoir à se soucier de connaître leur taille exacte (ce qui est requis pour la structure), vous pouvez facilement écrire une fonction d'aide qui divise ces nombres en octets séparés:

def splitNumber (num):
    lst = []
    while num > 0:
        lst.append(num & 0xFF)
        num >>= 8
    return lst[::-1]

bytes(splitNumber(12345678901234567890))
# b'\xabT\xa9\x8c\xeb\x1f\n\xd2'

Donc, si vous avez une liste de nombres, vous pouvez facilement les parcourir et les écrire dans le fichier; si vous souhaitez extraire les numéros individuellement plus tard, vous souhaiterez probablement ajouter quelque chose qui garde la trace des octets individuels appartenant à quels numéros.

with open(fileName, 'br+') as f:
    for number in numbers:
        f.write(bytes(splitNumber(number)))
32
poke

où binaire est une liste contenant des nombres

Un nombre peut avoir mille et une représentations binaires différentes (endianess, largeur, complément 1, complément 2, flotteurs de précision différente, etc.). Vous devez donc d'abord décider dans quelle représentation vous souhaitez stocker vos numéros. Ensuite, vous pouvez utiliser le module struct pour ce faire.

Par exemple, la séquence d'octets 0x3480 peut être interprétée comme 32820 (petit-boutiste non signé court), ou -32716 (petit-boutien signé court) ou 13440 (grand-boutien court).

Petit exemple:

#! /usr/bin/python3

import struct

binary = [1234, 5678, -9012, -3456]
with open('out.bin', 'wb') as f:
    for b in binary:
        f.write(struct.pack('h', b)) #or whatever format you need

with open('out.bin', 'rb') as f:
    content = f.read()
    for b in content:
        print(b)
    print(struct.unpack('hhhh', content)) #same format as above

impressions

210
4
46
22
204
220
128
242
(1234, 5678, -9012, -3456)
13
Hyperboreus