Converter string em binário em python

106

Estou precisando de uma maneira de obter a representação binária de uma string em python. por exemplo

st = "hello world"
toBinary(st)

Existe um módulo de alguma maneira legal de fazer isso?

user1090614
fonte
8
Qual você espera que seja a saída, especificamente?
NPE de
Por "binário", você quer dizer o tipo 0101010 ou o ordnúmero final de cada caractere em (por exemplo, hex)?
cdarke de
Supondo que você realmente quer dizer binário (zeros e uns), você quer uma representação binária de cada caractere (8 bits por caractere), um após o outro? por exemplo, h é o valor ascii 104 seria 01101000 em binário
ChrisProsser
Esta pergunta foi respondida várias vezes em stackoverflow: stackoverflow.com/questions/11599226/… stackoverflow.com/questions/8553310/…
0xcaff

Respostas:

124

Algo assim?

>>> 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
fonte
21
Ou se você quiser que cada número binário tenha 1 byte: '' .join (formato (ord (i), 'b'). Zfill (8) para i em st)
ChrisProsser
5
Para bytes completos você também pode usar ' '.join('{0:08b}'.format(ord(x), 'b') for x in st), que é cerca de 35% mais rápido do que a zfill(8)solução (pelo menos na minha máquina).
máx.
Que tal converter caracteres de mais de um byte, como β, por exemplo, o que me parece representado por 11001110 10110010internamente?
Sergey Bushmanov,
1
Sei que isso foi postado há muito tempo, mas e os caracteres não ASCII?
pkqxdd
48

Como uma maneira mais pythônica, você pode primeiro converter sua string em uma matriz de bytes e usar a binfunção em map:

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

Ou você pode participar:

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

Observe que em python3 você precisa especificar uma codificação para a bytearrayfunção:

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

Você também pode usar o binasciimódulo em Python 2:

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

hexlifyretornar a representação hexadecimal dos dados binários, então você pode converter para int especificando 16 como sua base e convertê-lo em binário com bin.

Kasravnd
fonte
5
Não apenas isso é mais pythônico, mas também é "mais" correto para strings não ASCII de vários bytes.
Sergey Bushmanov,
Apenas para notar que (pelo menos para a versão atual 3.7.4): (1) bytearrayespera uma codificação (não apenas uma string) e (2) map(bin, ...)irá retornar o mapobjeto. Para o primeiro ponto, eu uso por exemplo bob.encoding ('ascii') `como sugerido por @Tao. Para o segundo, aponte, usando o joinmétodo, como nos outros exemplos de @Kasramvd irá exibir o resultado desejado.
Antoine
36

Só precisamos codificá-lo.

'string'.encode('ascii')
Tao
fonte
Para mim ( v3.7.4), isso retorna um bytesobjeto (com as representações ASCII de cada byte, se disponível), e para exibir sua representação binária, eu preciso bin, por exemplo, com ' '.join(item[2:] for item in map(bin, 'bob'.encode('ascii')))(note que 0bprecisa ser removido no início da representação binária de cada personagem).
Antoine
15

Você pode acessar os valores do código para os caracteres em sua string usando a ord()função interna. Se você precisar formatar isso em binário, o string.format()método fará o trabalho.

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

(Agradecimentos a Ashwini Chaudhary por postar esse snippet de código.)

Embora o código acima funcione no Python 3, essa questão fica mais complicada se você assumir qualquer codificação diferente de UTF-8. No Python 2, as strings são sequências de bytes e a codificação ASCII é assumida por padrão. No Python 3, as strings são consideradas Unicode e há um bytestipo separado que atua mais como uma string Python 2. Se desejar assumir qualquer codificação diferente de UTF-8, você precisará especificar a codificação.

Em Python 3, então, você pode fazer algo assim:

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

As diferenças entre a codificação UTF-8 e ascii não serão óbvias para strings alfanuméricas simples, mas se tornarão importantes se você estiver processando texto que inclui caracteres que não estão no conjunto de caracteres ascii.

Mark R. Wilkins
fonte
2

No Python versão 3.6 e superior, você pode usar a string f para formatar o resultado.

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

01101000 01100101 01101100 01101100 01101111 00100000 01110111 01101111 01110010 01101100 01100100
  • O lado esquerdo dos dois pontos, ord (i), é o objeto real cujo valor será formatado e inserido na saída. Usar ord () fornece o ponto de código de base 10 para um único caractere str.

  • O lado direito dos dois pontos é o especificador de formato. 08 significa largura 8, 0 preenchido e as funções b como um sinal de saída do número resultante na base 2 (binário).

Vlad Bezden
fonte
1

Esta é uma atualização para as respostas existentes que costumavam bytearray()e não podem mais funcionar dessa forma:

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

Porque, conforme explicado no link acima, se a fonte for uma string, você também deve fornecer a codificação :

>>> map(bin, bytearray(st, encoding='utf-8'))
<map object at 0x7f14dfb1ff28>
Billal Begueradj
fonte
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 é substancialmente mais eficiente na conversão para uma matriz de bytes porque faz chamadas de função de baixo nível em vez de transformar manualmente cada caractere em um inteiro e, em seguida, converter esse inteiro em seu valor binário.

Ben
fonte
-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))
Navio Solo
fonte
1
Você gostaria de aumentar esta resposta ilegível apenas de código com alguma explicação? Isso ajudaria a combater o equívoco de que StackOverflow é um serviço de escrita de código gratuito. Caso você queira melhorar a legibilidade, experimente as informações fornecidas aqui: stackoverflow.com/editing-help
Yunnosch