96 votes

Conversion de binaire en ASCII et vice versa

Utiliser ce code pour prendre une chaîne et la convertir en binaire :

bin(reduce(lambda x, y: 256*x+y, (ord(c) for c in 'hello'), 0))

ces sorties :

0b110100001100101011011000110110001101111

Ce qui, si je le mets dans ce site (sur le site de droite) je reçois mon message de hello retour. Je me demande quelle méthode il utilise. Je sais que je pourrais découper la chaîne de caractères binaires en 8, puis la faire correspondre à la valeur correspondante de bin(ord(character)) ou d'une autre manière. Je cherche vraiment quelque chose de plus simple.

1 votes

Votre question est donc "existe-t-il un moyen plus succinct que l'évident pour faire l'inverse de mon code" ?

1 votes

Liés : b2a_bin en Cython permet de créer des chaînes de caractères binaires ( "01" ) directement à partir de bytestrings sans créer un entier Python intermédiaire.

174voto

J.F. Sebastian Points 102961

Pour les caractères ASCII dans la plage [ -~] sur Python 2 :

>>> import binascii
>>> bin(int(binascii.hexlify('hello'), 16))
'0b110100001100101011011000110110001101111'

En sens inverse :

>>> n = int('0b110100001100101011011000110110001101111', 2)
>>> binascii.unhexlify('%x' % n)
'hello'

Dans Python 3.2+ :

>>> bin(int.from_bytes('hello'.encode(), 'big'))
'0b110100001100101011011000110110001101111'

En sens inverse :

>>> n = int('0b110100001100101011011000110110001101111', 2)
>>> n.to_bytes((n.bit_length() + 7) // 8, 'big').decode()
'hello'

Pour supporter tous les caractères Unicode dans Python 3 :

def text_to_bits(text, encoding='utf-8', errors='surrogatepass'):
    bits = bin(int.from_bytes(text.encode(encoding, errors), 'big'))[2:]
    return bits.zfill(8 * ((len(bits) + 7) // 8))

def text_from_bits(bits, encoding='utf-8', errors='surrogatepass'):
    n = int(bits, 2)
    return n.to_bytes((n.bit_length() + 7) // 8, 'big').decode(encoding, errors) or '\0'

Voici la version compatible Python 2/3 à source unique :

import binascii

def text_to_bits(text, encoding='utf-8', errors='surrogatepass'):
    bits = bin(int(binascii.hexlify(text.encode(encoding, errors)), 16))[2:]
    return bits.zfill(8 * ((len(bits) + 7) // 8))

def text_from_bits(bits, encoding='utf-8', errors='surrogatepass'):
    n = int(bits, 2)
    return int2bytes(n).decode(encoding, errors)

def int2bytes(i):
    hex_string = '%x' % i
    n = len(hex_string)
    return binascii.unhexlify(hex_string.zfill(n + (n & 1)))

Exemple

>>> text_to_bits('hello')
'0110100001100101011011000110110001101111'
>>> text_from_bits('110100001100101011011000110110001101111') == u'hello'
True

3 votes

@J.F.Sebastian i tried this method with the python current version and it seems that it does not work. <br/>TypeError : 'str' ne supporte pas l'interface buffer <br/>Pourriez-vous mettre à jour votre réponse.

3 votes

@hamza : Cela fonctionne sur Python 2. Sur Python 3, vous devez d'abord convertir str en bytes, par exemple, your_string.encode('ascii', 'strict')

1 votes

@J.F.Sebasitian : merci, mais lorsque j'ai essayé l'inverse, la fonction unhexlify a renvoyé un message d'erreur : binascii.Error : Chaîne de longueur impaire.

10voto

agf Points 45052

Je ne sais pas comment vous pensez pouvoir le faire autrement que caractère par caractère - c'est par nature une opération caractère par caractère. Il existe certainement du code pour le faire à votre place, mais il n'y a pas de moyen plus "simple" que de le faire caractère par caractère.

Tout d'abord, vous devez dépouiller le 0b et mettre à zéro la chaîne de manière à ce que sa longueur soit divisible par 8, afin de faciliter la division de la chaîne de bits en caractères :

bitstring = bitstring[2:]
bitstring = -len(bitstring) % 8 * '0' + bitstring

Ensuite, vous divisez la chaîne en blocs de huit chiffres binaires, vous les convertissez en caractères ASCII et vous les réunissez en une chaîne :

string_blocks = (bitstring[i:i+8] for i in range(0, len(bitstring), 8))
string = ''.join(chr(int(char, 2)) for char in string_blocks)

Si vous voulez le traiter comme un nombre, vous devez tenir compte du fait que le caractère le plus à gauche sera au maximum de sept chiffres si vous voulez aller de gauche à droite plutôt que de droite à gauche.

2voto

C'est ma façon de résoudre votre problème :

str = "0b110100001100101011011000110110001101111"
str = "0" + str[2:]
message = ""
while str != "":
    i = chr(int(str[:8], 2))
    message = message + i
    str = str[8:]
print message

0 votes

Pourquoi ajoutez-vous le '0' à str = "0" + str[2 :] ? 0b doit être supprimé ici car c'est le début.

1voto

Jaxidian Points 4946

Vous cherchez le code pour le faire ou à comprendre l'algorithme ?

Est-ce que cela fait ce dont vous avez besoin ? Plus précisément a2b_uu y b2a_uu ? Il y a BEAUCOUP d'autres options au cas où ce ne serait pas ce que vous voulez.

(NOTE : Je ne suis pas un spécialiste des Pythons, mais la réponse me semble évidente).

0 votes

J'ai fait quelques recherches, binascii ne fonctionne pas pour moi, et je cherche surtout le code, si je peux le voir je peux le comprendre. Merci quand même EDIT : lors de la conversion de l'ascii en binaire en utilisant binascii, a2b_uu pour "h" est \x00\x00\x00\x00\x00\x00\x00\x00 ce qui n'est pas ce dont j'ai besoin, j'ai besoin de 'hello' et de vrais 1 et 0, pas d'un ascii ressemblant à un shellcode, et cela ne fonctionne que caractère par caractère.

0 votes

@Jaxidian, cela a été très utile pour moi. Quelqu'un a stocké des données dans une chaîne et je les ai. Je suis sûr que c'est un 64binaire à cause du remplissage. Je peux utiliser avec succès b2a_base64 sur ce point, mais le résultat est, en effet, confus au mieux. Comment puis-je obtenir une liste de booléens/entiers (0,1) à partir de là ?

-1voto

TH33L1T3 Points 1

C'est une version améliorée de celle de J.F. Sebastian. Merci pour les extraits de J.F. Sebastian.

import binascii, sys
def goodbye():
    sys.exit("\n"+"*"*43+"\n\nGood Bye! Come use again!\n\n"+"*"*43+"")
while __name__=='__main__':
    print "[A]scii to Binary, [B]inary to Ascii, or [E]xit:"
    var1=raw_input('>>> ')
    if var1=='a':
        string=raw_input('String to convert:\n>>> ')
        convert=bin(int(binascii.hexlify(string), 16))
        i=2
        truebin=[]
        while i!=len(convert):
            truebin.append(convert[i])
            i=i+1
        convert=''.join(truebin)
        print '\n'+'*'*84+'\n\n'+convert+'\n\n'+'*'*84+'\n'
    if var1=='b':
        binary=raw_input('Binary to convert:\n>>> ')
        n = int(binary, 2)
        done=binascii.unhexlify('%x' % n)
        print '\n'+'*'*84+'\n\n'+done+'\n\n'+'*'*84+'\n'
    if var1=='e':
        aus=raw_input('Are you sure? (y/n)\n>>> ')
        if aus=='y':
            goodbye()

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X