web-dev-qa-db-ja.com

Pythonで文字列をバイナリに変換する

私はPythonで文字列のバイナリ表現を取得する方法が必要です。例えば.

st = "hello world"
toBinary(st)

これを行うためのいくつかの良い方法のモジュールはありますか?

74
user1090614

このようなもの?

>>> 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))
'1101000 1100101 1101100 1101100 1101111 100000 1110111 1101111 1110010 1101100 1100100'
94

よりPythonicな方法としては、まず文字列をバイト配列に変換してから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'

pythonではbytearray関数のエンコーディングを指定する必要があることに注意してください。

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

Python 2ではbinasciiモジュールを使うこともできます。

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

hexlifyはバイナリデータの16進表現を返すので、そのベースとして16を指定してintに変換してから、それをbinでバイナリに変換することができます。

37
Kasrâmvd

ord()組み込み関数を使用して、文字列内の文字のコード値にアクセスできます。その後、これをバイナリでフォーマットする必要がある場合は、string.format()メソッドが役目を果たします。

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

(そのコードスニペットを投稿してくれたAshwini Chaudharyに感謝します。)

上記のコードはPython 3でも機能しますが、UTF-8以外のエンコーディングを想定している場合、この問題はさらに複雑になります。 Python 2では、文字列はバイトシーケンスであり、ASCIIエンコーディングはデフォルトで想定されています。 Python 3では、文字列はUnicodeであると想定されており、Python 2の文字列のように動作する別のbytes型があります。 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文字セットに含まれていない文字を含むテキストを処理している場合は重要になります。

15
Mark R. Wilkins

エンコードするだけです。

'string'.encode('ascii')
14
Tao

これは、 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>
1

Pythonバージョン3.6以降では、結果をフォーマットするために 'f-string'を使用できます。

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()を使用すると、1つのstr文字に対する10進数のコードポイントが得られます。

  • コロンの右側はフォーマット指定子です。 08は幅8、0の埋め込みを意味し、bは符号として機能し、結果の数値を2進数(2進数)で出力します。

0
Vlad Bezden
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 __== '__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は、手動ですべての文字を整数に変換してからその整数をバイナリ値に変換するのではなく、低レベルの関数呼び出しを行うため、バイト配列への変換において実質的により効率的です。

0
Ben