Convertir une chaîne en binaire en python

106

J'ai besoin d'un moyen d'obtenir la représentation binaire d'une chaîne en python. par exemple

st = "hello world"
toBinary(st)

Existe-t-il un module sur une manière intéressante de procéder?

user1090614
la source
8
À quoi vous attendez-vous en particulier pour la sortie?
NPE
Par "binaire", voulez-vous dire le type 0101010 ou le ordnuméro inal de chaque caractère (par exemple hexadécimal)?
cdarke
En supposant que vous vouliez dire binaire (zéros et uns), voulez-vous une représentation binaire de chaque caractère (8 bits par caractère) l'un après l'autre? Par exemple, h est la valeur ascii 104 serait 01101000 en binaire
ChrisProsser
Cette question a reçu plusieurs réponses sur stackoverflow: stackoverflow.com/questions/11599226/… stackoverflow.com/questions/8553310/…
0xcaff

Réponses:

124

Quelque chose comme ça?

>>> st = "hello world"
>>> ' '.join(format(ord(x), 'b') for x in st)
'1101000 1100101 1101100 1101100 1101111 100000 1110111 1101111 1110010 1101100 1100100'

#using `bytearray`
>>> ' '.join(format(x, 'b') for x in bytearray(st, 'utf-8'))
'1101000 1100101 1101100 1101100 1101111 100000 1110111 1101111 1110010 1101100 1100100'
Ashwini Chaudhary
la source
21
Ou si vous voulez que chaque nombre binaire soit de 1 octet: `` .join (format (ord (i), 'b'). Zfill (8) for i in st)
ChrisProsser
5
Pour les octets complets, vous pouvez également utiliser ' '.join('{0:08b}'.format(ord(x), 'b') for x in st), ce qui est environ 35% plus rapide que la zfill(8)solution (du moins sur ma machine).
max
Qu'en est-il de la conversion de caractères de plus d'un octet, comme β, par exemple, ce qui me semble représenté par en 11001110 10110010interne?
Sergey Bushmanov
1
Je sais que cela a été publié il y a longtemps, mais qu'en est-il des caractères non ASCII?
pkqxdd
48

De manière plus pythonique, vous pouvez d'abord convertir votre chaîne en tableau d'octets, puis utiliser la binfonction dans map:

>>> st = "hello world"
>>> map(bin,bytearray(st))
['0b1101000', '0b1100101', '0b1101100', '0b1101100', '0b1101111', '0b100000', '0b1110111', '0b1101111', '0b1110010', '0b1101100', '0b1100100']

Ou vous pouvez le rejoindre:

>>> ' '.join(map(bin,bytearray(st)))
'0b1101000 0b1100101 0b1101100 0b1101100 0b1101111 0b100000 0b1110111 0b1101111 0b1110010 0b1101100 0b1100100'

Notez que dans python3, vous devez spécifier un encodage pour la bytearrayfonction:

>>> ' '.join(map(bin,bytearray(st,'utf8')))
'0b1101000 0b1100101 0b1101100 0b1101100 0b1101111 0b100000 0b1110111 0b1101111 0b1110010 0b1101100 0b1100100'

Vous pouvez également utiliser le binasciimodule en python 2:

>>> import binascii
>>> bin(int(binascii.hexlify(st),16))
'0b110100001100101011011000110110001101111001000000111011101101111011100100110110001100100'

hexlifyretourne la représentation hexadécimale des données binaires, puis vous pouvez convertir en int en spécifiant 16 comme base puis le convertir en binaire avec bin.

Kasravnd
la source
5
Non seulement c'est plus pythonique, mais c'est «plus» correct pour les chaînes multi-octets non ASCII.
Sergey Bushmanov
Juste pour noter que (du moins pour la version actuelle 3.7.4): (1) bytearrayattend un encodage (pas seulement une chaîne) et (2) map(bin, ...)retournera l' mapobjet. Pour le premier point, j'utilise par exemple bob.encoding ('ascii') `comme suggéré par @Tao. Pour le second, pointez, en utilisant la joinméthode, comme dans les autres exemples de @Kasramvd affichera le résultat souhaité.
Antoine
36

Nous avons juste besoin de l'encoder.

'string'.encode('ascii')
Tao
la source
Pour moi ( v3.7.4), cela retourne un bytesobjet (avec les représentations ascii de chaque octet, si disponible), et pour afficher sa représentation binaire, j'ai besoin bin, par exemple avec ' '.join(item[2:] for item in map(bin, 'bob'.encode('ascii')))(note qui 0bdoit être supprimée au début de la représentation binaire de chaque personnage).
Antoine
15

Vous pouvez accéder aux valeurs de code pour les caractères de votre chaîne à l'aide de la ord()fonction intégrée. Si vous devez ensuite formater cela en binaire, la string.format()méthode fera le travail.

a = "test"
print(' '.join(format(ord(x), 'b') for x in a))

(Merci à Ashwini Chaudhary d'avoir publié cet extrait de code.)

Bien que le code ci-dessus fonctionne en Python 3, cette question se complique si vous supposez un encodage autre que UTF-8. Dans Python 2, les chaînes sont des séquences d'octets et le codage ASCII est supposé par défaut. Dans Python 3, les chaînes sont supposées être Unicode, et il existe un bytestype distinct qui agit plus comme une chaîne Python 2. Si vous souhaitez assumer un encodage autre que UTF-8, vous devrez spécifier l'encodage.

Dans Python 3, vous pouvez donc faire quelque chose comme ceci:

a = "test"
a_bytes = bytes(a, "ascii")
print(' '.join(["{0:b}".format(x) for x in a_bytes]))

Les différences entre le codage UTF-8 et ascii ne seront pas évidentes pour les chaînes alphanumériques simples, mais deviendront importantes si vous traitez du texte qui comprend des caractères ne faisant pas partie du jeu de caractères ascii.

Mark R. Wilkins
la source
2

Dans Python version 3.6 et supérieure, vous pouvez utiliser une chaîne f pour formater le résultat.

str = "hello world"
print(" ".join(f"{ord(i):08b}" for i in str))

01101000 01100101 01101100 01101100 01101111 00100000 01110111 01101111 01110010 01101100 01100100
  • Le côté gauche des deux points, ord (i), est l'objet réel dont la valeur sera formatée et insérée dans la sortie. L'utilisation de ord () vous donne le point de code en base 10 pour un seul caractère str.

  • Le côté droit des deux points est le spécificateur de format. 08 signifie largeur 8, 0 rembourré et le b fonctionne comme un signe pour sortir le nombre résultant en base 2 (binaire).

Vlad Bezden
la source
1

Ceci est une mise à jour pour les réponses existantes qui utilisaient bytearray()et ne peuvent plus fonctionner de cette façon:

>>> st = "hello world"
>>> map(bin, bytearray(st))
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: string argument without an encoding

Car, comme expliqué dans le lien ci-dessus, si la source est une chaîne, vous devez également donner l'encodage :

>>> map(bin, bytearray(st, encoding='utf-8'))
<map object at 0x7f14dfb1ff28>
Billal Begueradj
la source
0
def method_a(sample_string):
    binary = ' '.join(format(ord(x), 'b') for x in sample_string)

def method_b(sample_string):
    binary = ' '.join(map(bin,bytearray(sample_string,encoding='utf-8')))


if __name__ == '__main__':

    from timeit import timeit

    sample_string = 'Convert this ascii strong to binary.'

    print(
        timeit(f'method_a("{sample_string}")',setup='from __main__ import method_a'),
        timeit(f'method_b("{sample_string}")',setup='from __main__ import method_b')
    )

# 9.564299999998184 2.943955828988692

method_b est nettement plus efficace pour la conversion en tableau d'octets car elle effectue des appels de fonction de bas niveau au lieu de transformer manuellement chaque caractère en entier, puis de convertir cet entier en sa valeur binaire.

Ben
la source
-1
a = list(input("Enter a string\t: "))
def fun(a):
    c =' '.join(['0'*(8-len(bin(ord(i))[2:]))+(bin(ord(i))[2:]) for i in a])
    return c
print(fun(a))
Navire solo
la source
1
Souhaitez-vous compléter cette réponse illisible en code uniquement avec quelques explications? Cela aiderait à combattre l'idée fausse selon laquelle StackOverflow est un service d'écriture de code gratuit. Si vous souhaitez améliorer la lisibilité, essayez les informations fournies ici: stackoverflow.com/editing-help
Yunnosch