Ubah string menjadi biner dengan python


106

Saya membutuhkan cara untuk mendapatkan representasi biner dari string dengan python. misalnya

st = "hello world"
toBinary(st)

Apakah ada modul cara yang tepat untuk melakukan ini?


8
Secara spesifik, apa yang Anda harapkan dari keluaran?
NPE

Yang Anda maksud dengan "biner" adalah jenis 0101010 atau ordnomor akhir dari setiap karakter dalam (misalnya hex)?
cdarke

Dengan asumsi bahwa yang Anda maksud adalah biner (nol dan satu), apakah Anda menginginkan representasi biner dari setiap karakter (8 bit per karakter) satu demi satu? misalnya h adalah ascii nilai 104 akan menjadi 01101000 dalam biner
ChrisProsser

Pertanyaan ini telah dijawab berkali-kali di stackoverflow: stackoverflow.com/questions/11599226/… stackoverflow.com/questions/8553310/…
0xcaff

Jawaban:


124

Sesuatu seperti ini?

>>> 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
Atau jika Anda ingin setiap bilangan biner menjadi 1 byte: ".join (format (ord (i), 'b'). Zfill (8) for i in st)
ChrisProsser

5
Untuk byte penuh Anda juga dapat menggunakan ' '.join('{0:08b}'.format(ord(x), 'b') for x in st), yaitu sekitar 35% lebih cepat daripada zfill(8)solusi (setidaknya di mesin saya).
maks

Bagaimana dengan mengubah karakter lebih dari satu byte, seperti β, misalnya, yang menurut saya direpresentasikan secara 11001110 10110010internal?
Sergey Bushmanov

1
Saya tahu ini sudah lama diposting, tapi bagaimana dengan karakter non-ASCII?
pkqxdd

48

Sebagai cara yang lebih pythonic, pertama-tama Anda dapat mengubah string Anda menjadi array byte kemudian menggunakan binfungsi di dalam map:

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

Atau Anda bisa bergabung:

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

Perhatikan bahwa di python3 Anda perlu menentukan pengkodean untuk bytearrayfungsi:

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

Anda juga dapat menggunakan binasciimodul di python 2:

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

hexlifymengembalikan representasi heksadesimal dari data biner kemudian Anda dapat mengonversinya ke int dengan menetapkan 16 sebagai basisnya kemudian mengubahnya menjadi biner dengan bin.


5
Tidak hanya ini lebih pythonic, tetapi ini "lebih" benar untuk string non-ASCII multi-byte.
Sergey Bushmanov

Hanya untuk dicatat bahwa (setidaknya untuk versi saat ini 3.7.4): (1) bytearraymengharapkan encoding (bukan hanya string) dan (2) map(bin, ...)akan mengembalikan mapobjek. Untuk poin pertama, saya menggunakan misalnya bob.encoding ('ascii') `seperti yang disarankan oleh @Tao. Untuk yang kedua, titik, menggunakan joinmetode, seperti pada contoh lain dari @Kasramvd akan menampilkan hasil yang diinginkan.
Antoine

36

Kami hanya perlu menyandikannya.

'string'.encode('ascii')

Bagi saya ( v3.7.4), ini mengembalikan bytesobjek (dengan representasi ascii dari setiap byte, jika tersedia), dan untuk menampilkan representasi binernya, saya perlu bin, misalnya dengan ' '.join(item[2:] for item in map(bin, 'bob'.encode('ascii')))(catatan yang 0bperlu dihapus di awal representasi biner dari setiap karakter).
Antoine

15

Anda dapat mengakses nilai kode untuk karakter dalam string Anda menggunakan ord()fungsi bawaan. Jika Anda kemudian perlu memformat ini dalam biner, string.format()metode ini akan melakukan pekerjaan itu.

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

(Terima kasih kepada Ashwini Chaudhary untuk memposting cuplikan kode itu.)

Meskipun kode di atas berfungsi dengan Python 3, masalah ini menjadi lebih rumit jika Anda mengasumsikan pengkodean apa pun selain UTF-8. Di Python 2, string adalah urutan byte, dan pengkodean ASCII diasumsikan secara default. Dalam Python 3, string diasumsikan sebagai Unicode, dan ada bytestipe terpisah yang bertindak lebih seperti string Python 2. Jika Anda ingin mengasumsikan pengkodean apa pun selain UTF-8, Anda harus menentukan pengkodeannya.

Dengan Python 3, Anda dapat melakukan sesuatu seperti ini:

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

Perbedaan antara pengkodean UTF-8 dan ascii tidak akan terlihat jelas untuk string alfanumerik sederhana, tetapi akan menjadi penting jika Anda memproses teks yang menyertakan karakter yang tidak ada dalam kumpulan karakter ascii.


2

Dalam Python versi 3.6 dan yang lebih baru, Anda dapat menggunakan f-string untuk memformat hasil.

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

01101000 01100101 01101100 01101100 01101111 00100000 01110111 01101111 01110010 01101100 01100100
  • Sisi kiri titik dua, ord (i), adalah objek sebenarnya yang nilainya akan diformat dan dimasukkan ke dalam keluaran. Menggunakan ord () memberi Anda titik kode basis 10 untuk karakter str tunggal.

  • Sisi kanan titik dua adalah penentu format. 08 artinya lebar 8, 0 empuk, dan b berfungsi sebagai tanda untuk mengeluarkan bilangan yang dihasilkan dalam basis 2 (biner).


1

Ini adalah pembaruan untuk jawaban yang sudah ada yang digunakan bytearray()dan tidak bisa berfungsi seperti itu lagi:

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

Karena seperti yang dijelaskan pada link di atas, jika source-nya berupa string, Anda juga harus memberikan encodingnya :

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

method_b secara substansial lebih efisien dalam mengonversi ke array byte karena itu membuat panggilan fungsi tingkat rendah daripada secara manual mengubah setiap karakter menjadi integer, dan kemudian mengubah integer itu menjadi nilai binernya.


-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
Apakah Anda ingin menambah jawaban hanya kode yang tidak terbaca ini dengan beberapa penjelasan? Itu akan membantu melawan kesalahpahaman bahwa StackOverflow adalah layanan penulisan kode gratis. Jika Anda ingin meningkatkan keterbacaan, coba info yang disediakan di sini: stackoverflow.com/editing-help
Yunnosch
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.