前回まで分割キーボードを作っていたが完成しやっと手になじんできた。
バイトデータから文字コードを推測する
chardetはちょっと遅い気がするが、判別可能な文字コード種別が豊富
nkfはちょっと速い気がするが、判別可能な文字コード種別が少ない。
日本語文字コードしか扱わないという前提ならばnkfの方が吉?。
nkfを利用する場合
import nkf
def getencoding(dat:bytes):
if b"\0" in dat:
return None
enc = nkf.guess(dat).lower()
if enc and enc == "shift_jis":
return "cp932"
elif enc == "binary":
return None
else:
return enc
chardetを利用する場合
import chardet
def getencoding(dat:bytes):
return chardet.detect(dat)["encoding"]
使い方
>>> getencoding("これは何?".encode("utf-8"))
'utf-8'
>>> getencoding("これは何?".encode("sjis"))
'cp932'
>>> getencoding("これは何?".encode("euc-jp"))
'euc-jp'
>>> getencoding("Какво е какво?".encode("cp1251"))
'windows-1251' # chardetベースのgetencodingのみ判別できた
活用例
文字コード不明のテキストファイルがある場合、
バイナリモードで読み込んでgetencodingに渡せば推測文字コードが得られる。
どこまで正確なのかはよくわからないが、、、
>>> fname = "/tmp/eucjp.txt"
>>> with open(fname, "rb") as f
... enc = getencoding(f.read())
... print(enc)
'euc-jp'
1Kバイトでも読めば十分なデータであればf.read(1024)としても良いだろう。
# discovery.py
import sys
from glob import glob
for a in sys.argv[1:]:
for fname in glob(a):
with open(fname, "rb") as f:
LT = f.readline()[-2:]
if LT == "\r\n":
print("改行コード:CRLF")
elif LT[-1] == "\r":
print("改行コード:CR")
elif LT[-1] == "\n":
print("改行コード:LF")
else:
print("改行コード:不明")
f.seek(0)
print("文字コード:" + getencoding(f.read(1024)))
数百MB~数GBのテキストファイルの文字コードと改行コードを調べたいため僕は以下のように回す
$ python discovery.py /tmp/*.txt /tmp/*.csv