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?

pengguna1090614
sumber
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'
Ashwini Chaudhary
sumber
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.

Kasravnd
sumber
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')
Tao
sumber
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.

Mark R. Wilkins
sumber
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).

Vlad Bezden
sumber
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>
Billal Begueradj
sumber
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.

Ben
sumber
-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))
Kapal Solo
sumber
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