#概要
- 16進数のテキストファイル --> バイナリファイルに変換する
test.txt
1234567890abcdef
この例でpython3.2以降なら、int.to_bytesを使って、
with open("test.txt") as fin, open("test.bin", "wb") as fout:
s = fin.read()
fout.write(int(s,16).to_bytes(len(s)//2,"big"))
とやってしまうのが簡単ですね。
以下は、空白や改行などが入っても対応する場合のコードです。
#コード
import re
with open('test.txt', 'r') as fin:
s = fin.read()
s = re.sub(r'[\r\n\t ]|0x', '', s)
bins = [int(a+b,16) for a, b in zip(s[::2], s[1::2])]
with open('test.bin', 'wb') as fout:
fout.write(bytearray(bins))
s = re.sub(r'[\r\n\t ]|0x', '', s)
改行/タブ/半角スペースと0x
を削除(置換)しています。
bins = [int(a+b,16) for a, b in zip(s[::2], s[1::2])]
aとbのペアで16進数を構成するように取り出して、リストに入れています。
for a, b in zip(s[::2], s[1::2])
をもう少し詳しく示すと以下の動きをしています。
In [59]: s = "1234567890abcdef"
...: for a, b in zip(s[::2], s[1::2]):
...: print(f"a={a}, b={b}")
a=1, b=2
a=3, b=4
a=5, b=6
a=7, b=8
a=9, b=0
a=a, b=b
a=c, b=d
a=e, b=f
##変換例1
概要記載の通り
##変換例2
- スペースや'0x'が入ったケース
test2.txt
0x12 0x34 0x56 0x78 0x90
##変換例3
- 2の倍数の文字数でないケース
test3.txt
1234
56789
abc
def
- 最後の文字がドロップする('f'が変換されない)
別の手法
@shiracamuさんのpython2での方法を参考にStack Overflowを検索。回答を総合すると、python3ではcodecsを用いて以下のように書けるようだ。
with_codecs.py
import codecs
with open('test.txt', 'r') as fin, open('test.bin', 'wb') as fout:
s = re.sub(r'[\r\n\t ]|0x', '', fin.read())
fout.write(bytearray(codecs.getdecoder("hex_codec")(s)[0])
#参考