概要
文字列のテストデータを動的に生成する場合、16進数とバイト列の相互変換が必要になります。整数とバイト列、16進数とバイト列の変換だけでなく表示方法にもさまざまな選択肢があります。文字列とバイト列の相互変換について調べた記事はこちらの記事に分割しました。
整数と16進数文字列の相互変換
ビルトインの format
関数や hex
を使うことができます。Python 2 系との互換性を保つのであれば、%
を使います。
>>> format(0xabcd, 'x')
'abcd'
>>> hex(0xabcd)
'0xabcd'
>>> '%02x' % 0xabcd
'abcd'
str.format も使うことができます。
>>> '{:02x}'.format(0xabcd)
'abcd'
16進数文字列を整数に変換するには int
を使います。
>>> int('0xabcd', 16)
43981
>>> int('abcd', 16)
43981
16進数文字列とバイト列の相互変換
bytes.fromhex と bytes.hex
bytes.fromhex
と bytes.hex
は組み込みのメソッドです。bytes.hex
は Python 3.5 で追加されました。
>>> bytes.fromhex('abcd')
b'\xab\xcd'
>>> b'\xab\xcd'.hex()
'abcd'
binascii.unhexlify と binascii.hexlify
binascii
モジュールをインポートする必要があります。
>>> import binascii
>>> binascii.unhexlify('abcd')
b'\xab\xcd'
>>> str(binascii.hexlify(b'\xab\xcd'), 'utf-8')
'abcd'
エイリアスも用意されています。
>>> binascii.a2b_hex('abcd')
b'\xab\xcd'
>>> str(binascii.b2a_hex(b'\xab\xcd'), 'utf-8')
'abcd'
codecs.decode と codecs.encode
binascii.a2b_hex()
と binascii.b2a_hex()
と同じとマニュアルに明記されています。
>>> import codecs
>>> codecs.decode('abcd', 'hex')
b'\xab\xcd'
>>> codecs.encode(b'\xab\xcd', 'hex')
b'abcd'
>>> str(b'abcd', 'utf-8')
'abcd'
codecs.getdecoder
と codecs.getencoder
はタプルを返します。
>>> codecs.getdecoder('hex')('abcd')
(b'\xab\xcd', 4)
>>> codecs.getencoder('hex')(b'\xab\xcd')
(b'abcd', 2)
>>> str(b'abcd', 'utf-8')
'abcd'
整数とバイト列の相互変換
int.to_bytes と int.from_bytes
Python 3.2 から利用できます。
>>> """ https://stackoverflow.com/a/30375198/531320 """
>>> x = 0xabcd
>>> x.to_bytes((x.bit_length() + 7) // 8, byteorder='big')
b'\xab\xcd'
>>> format(int.from_bytes(b'\xab\xcd', byteorder='big'), 'x')
'abcd'
struct.pack と struct.unpack
struct.pack
、struct.unpack
で使えるフォーマットの記号の意味はほかのプログラミング言語と異なります。
>>> struct.pack('BB', 0xab, 0xcd)
b'\xab\xcd'
リストをパックして渡すことができます。
>>> x = [0xab, 0xcd]
>>> struct.pack('B'* len(x), *x)
b'\xab\xcd'
struct.unpack
はタプルを返します。
>>> x = b'\xab\xcd'
>>> struct.unpack('B' * len(x), x)
(171, 205)
16進数文字列経由
整数を16進数文字列に変換してから文字列に変換する方法もあります。メリットは整数の桁数を指定しなくてよいことです。
>>> bytes.fromhex(format(0xabcd, 'x'))
b'\xab\xcd'
>>> b'\xab\xcd'.hex()
'abcd'
>>> int(b'\xab\xcd'.hex(), 16)
43981
>>> 0xabcd
43981