En utilisant Python Comment puis-je lire les bits dans un octet?

J'ai un fichier où le premier octet contient des informations codées. Dans Matlab, je peux lire l'octet bit par bit var = fread(file, 8, 'ubit1'), puis les récupérer pour chaque bit par var(1), var(2), etc.

Y a-t-il un lecteur de bits équivalent en python?

28
demandé sur Andreas 2010-04-05 06:57:27

9 réponses

Lire les bits d'un fichier, bits bas en premier.

def bits(f):
    bytes = (ord(b) for b in f.read())
    for b in bytes:
        for i in xrange(8):
            yield (b >> i) & 1

for b in bits(open('binary-file.bin', 'r')):
    print b
24
répondu 2010-04-05 08:22:42

La plus petite unité avec laquelle vous pourrez travailler est un octet. Pour travailler au niveau du bit, vous devez utiliser opérateurs bit à bit .

x = 3
#Check if the 1st bit is set:
x&1 != 0
#Returns True

#Check if the 2nd bit is set:
x&2 != 0
#Returns True

#Check if the 3rd bit is set:
x&4 != 0
#Returns False
18
répondu Brian R. Bondy 2010-04-05 02:58:18

Vous ne pourrez pas lire chaque bit un par un-vous devez le lire octet par octet. Vous pouvez facilement extraire les bits, cependant:

f = open("myfile", 'rb')
# read one byte
byte = f.read(1)
# convert the byte to an integer representation
byte = ord(byte)
# now convert to string of 1s and 0s
byte = bin(byte)[2:].rjust(8, '0')
# now byte contains a string with 0s and 1s
for bit in byte:
    print bit
10
répondu Daniel G 2010-04-05 03:56:26

Avec numpy c'est facile comme ceci:

Bytes = numpy.fromfile(filename, dtype = "uint8")
Bits = numpy.unpackbits(Bytes)

Plus d'infos ici:
http://docs.scipy.org/doc/numpy/reference/generated/numpy.fromfile.html

8
répondu Mikhail V 2016-09-29 16:31:37

Pour lire un octet à partir d'un fichier: bytestring = open(filename, 'rb').read(1). Remarque: le fichier est ouvert dans le binaire mode.

Pour obtenir des morceaux, de les convertir bytestring en entier: byte = bytestring[0] (Python 3) ou byte = ord(bytestring[0]) (Python 2) et extraire les bits: (byte >> i) & 1:

>>> for i in range(8): (b'a'[0] >> i) & 1
... 
1
0
0
0
0
1
1
0
>>> bin(b'a'[0])
'0b1100001'
4
répondu jfs 2016-05-12 14:16:43

Il y a deux façons possibles de retourner le i-ème bit d'un octet. Le "premier bit" pourrait se référer au bit d'ordre Élevé ou au bit d'ordre inférieur.

Voici une fonction qui prend une chaîne et un index comme paramètres et renvoie la valeur du bit à cet emplacement. Comme écrit, il traite le bit de faible ordre comme le premier bit. Si vous voulez d'abord le bit d'ordre Élevé, décommentez simplement la ligne indiquée.

def bit_from_string(string, index):
       i, j = divmod(index, 8)

       # Uncomment this if you want the high-order bit first
       # j = 8 - j

       if ord(string[i]) & (1 << j):
              return 1
       else:
              return 0

L'indexation commence à 0. Si vous voulez que l'indexation commencez à 1, vous pouvez ajuster l'index dans la fonction avant d'appeler divmod.

Exemple d'utilisation:

>>> for i in range(8):
>>>       print i, bit_from_string('\x04', i)
0 0
1 0
2 1
3 0
4 0
5 0
6 0
7 0

Maintenant, Pour comment cela fonctionne:

Une chaîne est composée d'octets de 8 bits, donc nous utilisons d'abord divmod () pour diviser l'index en parties:

  • i: l'index de l'octet correct dans la chaîne
  • j: l'indice du bit correct dans cet octet

Nous utilisons la fonction ord() pour convertir le caractère à string[i] en un type entier. Puis, (1 << j) calcule la valeur du J-ème bit en décalant à gauche 1 de j. Enfin, nous utilisons bit à bit-et pour tester si ce bit est défini. Si c'est le cas, retournez 1, sinon retournez 0.

2
répondu Daniel Stutzbach 2010-04-05 03:52:45

Rejoindre certaines des réponses précédentes que j'utiliserais:

[int(i) for i in "{0:08b}".format(byte)]

Pour chaque octet lu dans le fichier. Les résultats pour un exemple d'octet 0x88 sont:

>>> [int(i) for i in "{0:08b}".format(0x88)]
[1, 0, 0, 0, 1, 0, 0, 0]

Vous pouvez l'affecter à une variable et travailler selon votre demande initiale. Le "{0.08} " est de garantir la longueur complète des octets

2
répondu Francisco 2017-01-04 04:44:34

C'est assez rapide je pense:

import itertools
data = range(10)
format = "{:0>8b}".format
newdata = (False if n == '0' else True for n in itertools.chain.from_iterable(map(format, data)))
print(newdata) # prints tons of True and False
0
répondu vitiral 2014-11-06 19:44:19

Supposons que vous ayez un fichier appelé bloom_filter.bin qui contient un tableau de bits et que vous voulez lire le fichier entier et utiliser ces bits dans un tableau.

Créez D'abord le tableau où les bits seront stockés après la lecture,

from bitarray import bitarray
a=bitarray(size)           #same as the number of bits in the file

Ouvre le fichier, en utilisant open ou avec, tout va bien...Je reste avec ouvert ici,

f=open('bloom_filter.bin','rb')

Maintenant charger tous les bits dans le tableau ' a ' à un seul coup en utilisant,

f.readinto(a)

" a " est maintenant bitarray contenant tous les bits

0
répondu Tarun 2015-05-15 08:34:37