web-dev-qa-db-fra.com

Utilisation de 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 petit à petit avec var = fread(file, 8, 'ubit1'), puis récupérer chaque bit par var(1), var(2), etc.

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

30
David

Lire les bits d'un fichier, les 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
user97370

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

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
Brian R. Bondy

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
Daniel G

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

9
Mikhail V

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

Pour obtenir des bits, convertissez la chaîne d'octets en un entier: byte = bytestring[0] (Python 3) ou byte = ord(bytestring[0]) (Python 2) et extrayez le bit souhaité: (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
jfs

Joindre certaines des réponses précédentes, je voudrais utiliser:

[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 les suivants:

>>> [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}" sert à garantir la longueur totale en octets.

2
Francisco

Il y a deux manières possibles de renvoyer le i-ème bit d'un octet. Le "premier bit" peut faire référence au bit de poids fort ou au bit de poids faible.

Voici une fonction qui prend une chaîne et un index en tant que paramètres et renvoie la valeur du bit à cet emplacement. Tel qu'écrit, il traite le bit de poids faible comme le premier bit. Si vous voulez d'abord le bit de poids fort, 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 souhaitez que l'indexation commence à 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 ça marche:

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

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

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

2
Daniel Stutzbach

Supposons que vous avez 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.

Commencez par créer 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

Ouvrez le fichier, En utilisant open ou avec, tout va bien ... je m'en tiens à open ici,

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

Maintenant, chargez tous les bits du tableau 'a' d'un coup en utilisant,

f.readinto(a)

'a' est maintenant un bitarray contenant tous les bits

0
Tarun

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
vitiral