web-dev-qa-db-fra.com

Ecrivez un entier binaire ou une chaîne dans un fichier en python

J'ai une chaîne (elle pourrait aussi être un entier) en Python et je veux l'écrire dans un fichier. Il ne contient que des uns et des zéros. Je veux que ce modèle de uns et de zéros soit écrit dans un fichier. Je veux écrire le binaire directement car j'ai besoin de stocker beaucoup de données, mais seulement certaines valeurs. Je ne vois pas la nécessité d'utiliser l'espace de huit bits par valeur alors qu'il n'en faut que trois.

Par exemple. Disons que je devais écrire la chaîne binaire "01100010" dans un fichier. Si je l'ouvrais dans un éditeur de texte, il dirait b (01100010 est le code ascii pour b). Ne soyez pas confus cependant. Je ne veux pas écrire de codes ASCII, l'exemple était juste pour indiquer que je voulais écrire directement des octets dans le fichier.


Clarification:

Ma chaîne ressemble à ceci:

binary_string = "001011010110000010010"

Il n'est pas composé de codes binaires pour les nombres ou les caractères. Il contient des données relatives uniquement à mon programme.

9
KFox

D'accord, après un peu plus de recherches, j'ai trouvé une réponse. Je crois que le reste d'entre vous n'a tout simplement pas compris (ce qui était probablement de ma faute, car j'ai dû modifier deux fois pour que tout soit clair). Je l'ai trouvé ici .

La solution consistait à fractionner chaque donnée, à les convertir en un entier binaire, puis à les placer dans un tableau binaire. Après cela, vous pouvez utiliser la méthode tofile() du tableau pour écrire dans un fichier.

from array import *

bin_array = array('B')

bin_array.append(int('011',2))
bin_array.append(int('010',2))
bin_array.append(int('110',2))

f = file('binary.mydata','wb')
bin_array.tofile(f)
f.close()
5
KFox

Pour écrire une chaîne, vous pouvez utiliser la méthode .write du fichier. Pour écrire un entier, vous devrez utiliser le module struct

import struct

#...
with open('file.dat', 'wb') as f:
    if isinstance(value, int):
        f.write(struct.pack('i', value)) # write an int
    Elif isinstance(value, str):
        f.write(value) # write a string
    else:
        raise TypeError('Can only write str or int')

Cependant, les représentations de int et string sont différentes, vous pouvez utiliser la fonction bin à la place pour la transformer en une chaîne de 0 et de 1.

>>> bin(7)
'0b111'
>>> bin(7)[2:] #cut off the 0b
'111'

mais peut-être que le meilleur moyen de gérer toutes ces ints est de choisir une largeur fixe pour les chaînes binaires du fichier et de les convertir comme suit:

>>> x = 7
>>> '{0:032b}'.format(x) #32 character wide binary number with '0' as filler
'00000000000000000000000000000111'
8
Ryan Haining

Je veux que ce modèle de uns et de zéros soit écrit dans un fichier.

Si vous voulez dire que vous voulez écrire un flux binaire d'une chaîne dans un fichier, vous aurez besoin de quelque chose comme ça ...

from cStringIO import StringIO

s = "001011010110000010010"
sio = StringIO(s)

f = open('outfile', 'wb')

while 1:
    # Grab the next 8 bits
    b = sio.read(8)

    # Bail if we hit EOF
    if not b:
        break

    # If we got fewer than 8 bits, pad with zeroes on the right
    if len(b) < 8:
        b = b + '0' * (8 - len(b))

    # Convert to int
    i = int(b, 2)

    # Convert to char
    c = chr(i)

    # Write
    f.write(c)

f.close()

... pour lequel xxd -b outfile indique ...

0000000: 00101101 01100000 10010000                             -`.
4
Aya

Bref exemple:

my_number = 1234
with open('myfile', 'wb') as file_handle:
    file_handle.write(struct.pack('i', my_number))
...
with open('myfile', 'rb') as file_handle:
    my_number_back = struct.unpack('i', file_handle.read())[0]
1
ThorSummoner

Ajouter à array.array 3 bits à la fois produira toujours 8 bits pour chaque valeur. Ajouter 011, 010 et 110 à un tableau et écrire sur le disque produiront la sortie suivante: 00000011 00000010 00000110. Notez tous les zéros remplis dedans.

Il semble plutôt que vous souhaitiez "compacter" les triplets binaires en octets pour économiser de l'espace. À l'aide de l'exemple de chaîne dans votre question, vous pouvez la convertir en une liste d'entiers (8 bits à la fois), puis l'écrire directement dans un fichier. Cela regroupera tous les bits en utilisant seulement 3 bits par valeur plutôt que 8.

Exemple Python 3.4

original_string = '001011010110000010010'

# first split into 8-bit chunks
bit_strings = [original_string[i:i + 8] for i in range(0, len(original_string), 8)]

# then convert to integers
byte_list = [int(b, 2) for b in bit_strings]

with open('byte.dat', 'wb') as f:
    f.write(bytearray(byte_list))  # convert to bytearray before writing

Contenu de byte.dat:

  • hex: 2D 60 12
  • binaire (par 8 bits): 00101101 01100000 00010010
  • binaire (par 3 bits): 001 011 010 110 000 000 010 010

                                        ^^ ^ (Note extra bits)
    

    Notez que cette méthode compile les dernières valeurs de manière à s'aligner sur une limite de 8 bits et que le remplissage opère sur les bits les plus significatifs (côté gauche du dernier octet dans la sortie ci-dessus). Vous devez donc faire attention et éventuellement ajouter des zéros à la fin de votre chaîne d'origine pour que la longueur de votre chaîne soit un multiple de 8.

0
jdk1.0