はじめに
Pythonでテキストファイルを扱う際、文字コードの自動判定が必要になることがあります。
多くのエンジニアが頼るのが chardet
か nkf
ライブラリ化と思いますが、必ずしも完璧ではありません。
実際にきょう私は業務で、chardet
を使っていて、Shift_JISのテキストファイルがWindows-1252と誤判定されるという事象に直面しました。
本記事では、その問題の再現と、業務で採用した安全な文字コード判定ロジックをご紹介します。
問題の発端:Shift_JISがWindows-1252と誤判定される
import chardet
with open("sample_sjis.txt", "rb") as f:
raw_data = f.read()
result = chardet.detect(raw_data)
print(result)
出力例
{'encoding': 'Windows-1252', 'confidence': 0.73, 'language': ''}
Shift_JISファイルなのに、Windows-1252 と判定されました。
なぜ誤判定が起きるのか?
- Shift_JISとWindows-1252のバイト表現が一部似ている
- chardet は統計的推定に基づいており、誤差が避けられない
- 英数字中心の日本語ファイルは特に誤判定されやすい
解決策:主要な文字コードを優先的に試す
chardet を最後の手段にして、一般的に使用が想定される主要なエンコーディングを先に順番に試みることで、安全性を確保します。
from pathlib import Path
import chardet
COMMON_ENCODINGS = ["utf-8", "shift_jis", "euc_jp", "iso2022_jp"]
def detect_encoding(filepath: Path) -> str:
content = filepath.read_bytes()
for enc in COMMON_ENCODINGS:
try:
content.decode(enc)
return enc
except UnicodeDecodeError:
continue
# 最終手段として chardet
result = chardet.detect(content)
return result["encoding"] or "utf-8"
# 使用例
file_path = Path("sample_sjis.txt")
detected = detect_encoding(file_path)
print(f"Detected encoding: {detected}")
まとめ
- chardet は便利だが、誤判定のリスクがある
- よく使われる文字コードを先に試すことで安全性を確保できる