web-dev-qa-db-fra.com

Conversion d'octets en bits en python

Je travaille avec Python3.2. Je dois prendre un flux hexadécimal en tant qu'entrée et l'analyser au niveau du bit. Alors j'ai utilisé

bytes.fromhex(input_str)

convertir la chaîne en octets réels. Maintenant, comment convertir ces octets en bits?

16
user904832

Une autre façon de faire est d’utiliser le module bitstring :

>>> from bitstring import BitArray
>>> input_str = '0xff'
>>> c = BitArray(hex=input_str)
>>> c.bin
'0b11111111'

Et si vous devez effacer le 0b qui précède:

>>> c.bin[2:]
'11111111'

Le module bitstring n'est pas une exigence, comme le montre la réponse de jcollado, mais il a beaucoup de méthodes performantes pour convertir les entrées en bits et les manipuler. Vous pourriez trouver cela pratique (ou pas), par exemple:

>>> c.uint
255
>>> c.invert()
>>> c.bin[2:]
'00000000'

etc.

26
Alex Reynolds

Qu'en est-il quelque chose comme ça?

>>> bin(int('ff', base=16))
'0b11111111'

Cela convertira la chaîne hexadécimale que vous avez en un entier et cet entier en une chaîne dans laquelle chaque octet est défini sur 0/1 en fonction de la valeur en bits de l'entier.

Comme le souligne un commentaire, si vous devez vous débarrasser du préfixe 0b, vous pouvez le faire de la manière suivante:

>>> bin(int('ff', base=16)).lstrip('0b')
11111111

ou de cette façon:

>>> bin(int('ff', base=16))[2:]
11111111
16
jcollado

Les opérations sont beaucoup plus rapides lorsque vous travaillez au niveau entier. En particulier, la conversion en chaîne, comme suggéré ici, est très lente.

Si vous voulez uniquement les bits 7 et 8, utilisez par exemple.

val = (byte >> 6) & 3

(c’est-à-dire: décaler l’octet de 6 bits vers la droite - les supprimer. Ne conservez alors que les deux derniers bits 3 est le numéro avec les deux premiers bits définis ...)

Celles-ci peuvent facilement être traduites en opérations simples et rapides du processeur.

16
Anony-Mousse

Pour binaire:

bin(byte)[2:].zfill(8)
7
Ferguzz

Je pense que le plus simple serait d'utiliser numpy ici. Par exemple, vous pouvez lire un fichier sous forme d'octets, puis le développer en bits facilement, comme ceci:

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

Utilisez ord lors de la lecture des octets de lecture:

byte_binary = bin(ord(f.read(1))) # Add [2:] to remove the "0b" prefix

Ou

Utilisation de str.format():

'{:08b}'.format(ord(f.read(1)))
1
Jacob Valenta

utilisation de python syntaxe de chaîne de format

>>> mybyte = bytes.fromhex("0F") # create my byte using a hex string
>>> binary_string = "{:08b}".format(int(mybyte.hex(),16))
>>> print(binary_string)
00001111

La deuxième ligne est l'endroit où la magie se produit. Tous les objets d'octet ont une fonction .hex() qui renvoie une chaîne hexadécimale. À l'aide de cette chaîne hexadécimale, nous la convertissons en un entier indiquant à la fonction int() qu'il s'agit d'une chaîne en base 16 (car hex est en base 16). Ensuite, nous appliquons le formatage à cet entier pour qu’il s’affiche sous la forme d’une chaîne binaire. Le {:08b} est l'endroit où la vraie magie se produit. Il utilise le mini-langage de spécification de format format_spec. Plus précisément, il utilise les parties width et type de la syntaxe format_spec. Le 8 définit width sur 8, ce qui permet d'obtenir le remplissage Nice 0000, et le b définit le type sur binaire.

Je préfère cette méthode à la méthode bin() car utiliser une chaîne de format donne beaucoup plus de flexibilité.

0
ZenCodr

Voici comment le faire en utilisant format() 

print "bin_signedDate : ", ''.join(format(x, '08b') for x in bytevector)

Il est important que le 08b . Cela signifie qu’un maximum de 8 zéros sera ajouté pour compléter un octet. Si vous ne spécifiez pas cela, le format aura simplement une longueur de bit variable pour chaque octet converti.

0
Joniale

Les autres réponses ici fournissent les bits dans big-endian order ('\x01' devient '00000001')

Dans le cas où vous seriez intéressé par l'ordre des bits little-endian, ce qui est utile dans de nombreux cas, comme les représentations courantes de bignums, etc., voici un extrait de ce code:

def bits_little_endian_from_bytes(s):
    return ''.join(bin(ord(x))[2:].rjust(8,'0')[::-1] for x in s)

Et pour l’autre direction:

def bytes_from_bits_little_endian(s):
    return ''.join(chr(int(s[i:i+8][::-1], 2)) for i in range(0, len(s), 8))
0
yairchu