Konwertuj ciąg na binarny w Pythonie


106

Potrzebuję sposobu, aby uzyskać binarną reprezentację ciągu w Pythonie. na przykład

st = "hello world"
toBinary(st)

Czy istnieje jakiś zgrabny sposób na zrobienie tego?


8
Jaki będzie konkretnie efekt końcowy?
— NPE

Czy przez „binarny” masz na myśli typ 0101010, czy też inal ordnumer każdego znaku (np. Szesnastkowy)?
— cdarke

Zakładając, że faktycznie masz na myśli binarne (zera i jedynki), czy chcesz binarną reprezentację każdego znaku (8 bitów na znak) jeden po drugim? np. h to ascii, wartość 104 byłaby binarna jako 01101000
— ChrisProsser

Na to pytanie odpowiadano wiele razy na stackoverflow: stackoverflow.com/questions/11599226/… stackoverflow.com/questions/8553310/…
— 0xcaff

Odpowiedzi:


124

Coś takiego?

>>> 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'

21
Lub jeśli chcesz, aby każda liczba binarna miała 1 bajt: '' .join (format (ord (i), 'b'). Zfill (8) for i in st)
— ChrisProsser

5
Do pełnych bajtów można również użyć ' '.join('{0:08b}'.format(ord(x), 'b') for x in st), co jest około 35% szybsze niż zfill(8)rozwiązanie (przynajmniej na moim komputerze).
— maks.

A co z konwersją znaków więcej niż jednobajtowych β, na przykład, które wydają mi się reprezentowane przez 11001110 10110010wewnętrznie?
— Sergey Bushmanov

1
Wiem, że to zostało opublikowane dawno temu, ale co ze znakami spoza ASCII?
— pkqxdd

48

W bardziej Pythonowym sposobie możesz najpierw przekonwertować swój ciąg na tablicę bajtów, a następnie użyć binfunkcji w map:

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

Lub możesz do niego dołączyć:

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

Zauważ, że w python3 musisz określić kodowanie bytearrayfunkcji:

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

Możesz także użyć binasciimodułu w Pythonie 2:

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

hexlifyzwróć szesnastkową reprezentację danych binarnych, a następnie możesz przekonwertować je na int, określając 16 jako podstawę, a następnie przekonwertuj je na binarne za pomocą bin.


5
Nie tylko jest to bardziej pythonowe, ale jest „bardziej” poprawne dla wielobajtowych ciągów innych niż ASCII.
— Sergey Bushmanov

Wystarczy zauważyć, że (przynajmniej dla bieżącej wersji 3.7.4): (1) bytearrayoczekuje kodowania (nie tylko ciągu znaków), a (2) map(bin, ...)zwróci mapobiekt. W pierwszym punkcie używam na przykład bob.encoding ('ascii') `zgodnie z sugestią @Tao. Po drugie, wskaż, używając joinmetody, tak jak w innych przykładach @Kasramvd wyświetli pożądany wynik.
— Antoine

36

Musimy to tylko zakodować.

'string'.encode('ascii')

Dla mnie ( v3.7.4) zwraca to bytesobiekt (z reprezentacjami ascii każdego bajtu, jeśli jest dostępny), a żeby wyświetlić jego binarną reprezentację potrzebuję binnp. With ' '.join(item[2:] for item in map(bin, 'bob'.encode('ascii')))(uwaga, którą 0bnależy usunąć na początku reprezentacji binarnej każdego znaku).
— Antoine,

15

Możesz uzyskać dostęp do wartości kodu dla znaków w ciągu za pomocą funkcji ord()wbudowanej. Jeśli potem będziesz musiał sformatować to w formacie binarnym, string.format()metoda wykona zadanie.

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

(Podziękowania dla Ashwini Chaudhary za opublikowanie tego fragmentu kodu).

Chociaż powyższy kod działa w Pythonie 3, sprawa staje się bardziej skomplikowana, jeśli zakładasz kodowanie inne niż UTF-8. W Pythonie 2 ciągi są sekwencjami bajtów i domyślnie zakłada się kodowanie ASCII. W Pythonie 3 przyjmuje się, że łańcuchy są kodami Unicode i istnieje oddzielny bytestyp, który działa bardziej jak łańcuch w Pythonie 2. Jeśli chcesz założyć kodowanie inne niż UTF-8, musisz określić kodowanie.

W Pythonie 3 możesz więc zrobić coś takiego:

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

Różnice między kodowaniem UTF-8 i ascii nie będą oczywiste w przypadku prostych ciągów alfanumerycznych, ale staną się ważne, jeśli przetwarzasz tekst zawierający znaki spoza zestawu znaków ascii.


2

W Pythonie w wersji 3.6 i nowszych możesz użyć f-string do sformatowania wyniku.

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

01101000 01100101 01101100 01101100 01101111 00100000 01110111 01101111 01110010 01101100 01100100
  • Lewa strona dwukropka, ord (i), to rzeczywisty obiekt, którego wartość zostanie sformatowana i wstawiona do wyniku. Użycie ord () daje punkt kodowy przy podstawie 10 dla pojedynczego znaku str.

  • Prawa strona dwukropka to specyfikator formatu. 08 oznacza szerokość 8, 0 wypełnione, a b działa jako znak, aby wyprowadzić wynikową liczbę w bazie 2 (binarnie).


1

To jest aktualizacja istniejących odpowiedzi, które były używane bytearray()i nie mogą już działać w ten sposób:

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

Ponieważ, jak wyjaśniono w powyższym linku, jeśli źródłem jest ciąg, musisz również podać kodowanie :

>>> map(bin, bytearray(st, encoding='utf-8'))
<map object at 0x7f14dfb1ff28>

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

Metoda method_b jest znacznie bardziej wydajna w konwertowaniu na tablicę bajtów, ponieważ wykonuje wywołania funkcji niskiego poziomu, zamiast ręcznie przekształcać każdy znak na liczbę całkowitą, a następnie konwertować tę liczbę całkowitą na jej wartość binarną.


-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))

1
Czy chciałbyś rozszerzyć tę nieczytelną odpowiedź zawierającą tylko kod o jakieś wyjaśnienie? Pomogłoby to w zwalczaniu błędnego przekonania, że ​​StackOverflow to bezpłatna usługa pisania kodu. Jeśli chcesz poprawić czytelność, wypróbuj informacje podane tutaj: stackoverflow.com/editing-help
— Yunnosch
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.