Преобразование строки в двоичный файл в Python

107

Мне нужен способ получить двоичное представление строки в python. например

st = "hello world"
toBinary(st)

Есть ли какой-нибудь изящный способ сделать это?

user1090614
источник
8
Какого конкретно результата вы ожидаете?
NPE
Под «двоичным» вы подразумеваете тип 0101010 или ordокончательный номер каждого символа в (например, шестнадцатеричный)?
cdarke
Предполагая, что вы на самом деле имеете в виду двоичные (нули и единицы), хотите ли вы двоичное представление каждого символа (8 бит на символ) один за другим? например, h - значение ascii 104, в двоичном
формате
На этот вопрос много раз ответили в stackoverflow: stackoverflow.com/questions/11599226/… stackoverflow.com/questions/8553310/…
0xcaff
возможный дубликат Convert Binary to ASCII и наоборот (Python)
jfs

Ответы:

124

Что-то вроде этого?

>>> 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'
Ашвини Чаудхари
источник
22
Или, если вы хотите, чтобы каждое двоичное число было 1 байтом: '' .join (format (ord (i), 'b'). Zfill (8) for i in st)
ChrisProsser
5
Для полных байтов вы также можете использовать ' '.join('{0:08b}'.format(ord(x), 'b') for x in st), что примерно на 35% быстрее, чем zfill(8)решение (по крайней мере, на моей машине).
максимум
Как насчет преобразования символов размером более одного байта, βнапример, которые, как мне кажется, представлены 11001110 10110010внутренне?
Сергей Бушманов
1
Я знаю, что это было опубликовано давно, но как насчет символов, отличных от ASCII?
pkqxdd
48

В качестве более питонического способа вы можете сначала преобразовать свою строку в массив байтов, а затем использовать binфункцию внутри map:

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

Или вы можете присоединиться к нему:

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

Обратите внимание, что в python3 вам нужно указать кодировку для bytearrayфункции:

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

Вы также можете использовать binasciiмодуль в python 2:

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

hexlifyвернуть шестнадцатеричное представление двоичных данных, затем вы можете преобразовать его в int, указав 16 в качестве его основы, а затем преобразовать его в двоичное с помощью bin.

Касравнд
источник
5
Это не только более питонично, но и «более» правильно для многобайтовых строк, отличных от ASCII.
Сергей Бушманов
Просто отметим, что (по крайней мере, для текущей версии 3.7.4): (1) bytearrayожидает кодировку (а не только строку) и (2) map(bin, ...)вернет mapобъект. Для первого пункта я использую, например, bob.encoding ('ascii') `, как это предлагает @Tao. Для второго пункта, используя joinметод, как и в других примерах @Kasramvd, отобразит желаемый результат.
Антуан
36

Нам просто нужно его закодировать.

'string'.encode('ascii')
Дао
источник
Для меня ( v3.7.4) это возвращает bytesобъект (с ascii-представлениями каждого байта, если они доступны), и для отображения его двоичного представления мне нужно bin, например, с ' '.join(item[2:] for item in map(bin, 'bob'.encode('ascii')))(обратите внимание, что 0bнеобходимо удалить в начале двоичного представления каждого персонажа).
Антуан
15

Вы можете получить доступ к кодовым значениям символов в вашей строке с помощью ord()встроенной функции. Если вам затем нужно отформатировать это в двоичном формате, string.format()метод выполнит свою работу.

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

(Спасибо Ашвини Чаудхари за публикацию этого фрагмента кода.)

Хотя приведенный выше код работает в Python 3, этот вопрос становится более сложным, если вы предполагаете любую кодировку, отличную от UTF-8. В Python 2 строки представляют собой байтовые последовательности, и по умолчанию предполагается кодировка ASCII. В Python 3 предполагается, что строки являются Unicode, и есть отдельный bytesтип, который больше похож на строку Python 2. Если вы хотите использовать любую кодировку, отличную от UTF-8, вам необходимо указать кодировку.

В Python 3 вы можете сделать что-то вроде этого:

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

Различия между кодировкой UTF-8 и ascii не будут очевидны для простых буквенно-цифровых строк, но станут важными, если вы обрабатываете текст, который включает символы, не входящие в набор символов ascii.

Марк Р. Уилкинс
источник
2

В Python версии 3.6 и выше вы можете использовать f-строку для форматирования результата.

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

01101000 01100101 01101100 01101100 01101111 00100000 01110111 01101111 01110010 01101100 01100100
  • Левая часть двоеточия, ord (i), является фактическим объектом, значение которого будет отформатировано и вставлено в вывод. Использование ord () дает вам кодовую точку base-10 для одного символа str.

  • Правая часть двоеточия - это спецификатор формата. 08 означает ширину 8, 0 с дополнением, а b действует как знак для вывода результирующего числа в базе 2 (двоичный).

Влад Безден
источник
1

Это обновление для существующих ответов, которые использовались bytearray()и больше не могут работать таким образом:

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

Поскольку, как объясняется в приведенной выше ссылке, если источник является строкой, вы также должны указать кодировку :

>>> 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 существенно более эффективен при преобразовании в массив байтов, поскольку он выполняет вызовы функций низкого уровня вместо того, чтобы вручную преобразовывать каждый символ в целое число, а затем преобразовывать это целое число в его двоичное значение.

Бен
источник
-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
Хотели бы вы дополнить этот нечитаемый ответ, состоящий только из кода, некоторыми пояснениями? Это поможет бороться с неправильным представлением о том, что StackOverflow - это бесплатный сервис для написания кода. Если вы хотите улучшить читаемость, попробуйте информацию, предоставленную здесь: stackoverflow.com/editing-help
Юннош