メインコンテンツへスキップ
【Python】テキストファイルの文字コードを判別してファイルを開く

【Python】テキストファイルの文字コードを判別してファイルを開く

·3 分
Programming Python
かずさプログラマー
著者
かずさプログラマー
業務の作業自動化を行っています。Go、VBA、Pythonを主に使用しています。過去にはC#、VB.Net、JavaScriptも使用していました。
目次

Pythonのopenで使用するencodingはプラットフォームに依存します。
Windowsであればcp932です。

Windows上のUTF-8で保存されたテキストファイルをencoding引数に何もつけずにopenするとエラーが発生します。

with open('UTF-8.txt') as f:
    s = f.read()
    print(s) # UnicodeDecodeError: 'cp932' codec can't decodeが発生する

テキストファイルを開く前に文字コードを判別してから適切なencoding引数で開くようにしてみます。

chardetを使用して文字コードを判別する
#

chardetを使用して、文字コードを判別します。

pipを使用してchardetをインストールします。

pip install chardet

UTF-8とShift-JISの文字コードのテキストファイルを用意して、それぞれ下記の内容でファイルを保存しました。

あいうえお

このテキストファイルをchardetのdetectメソッドを使用してテキストファイルの文字コードを判別してみます。

detectメソッドの引数にはbytesまたはbytearrayを渡す必要があります。
openでファイルを開くときにmodeの引数にrbを指定し、バイナリモードで読み込んだファイルを detectの引数として使用します。

import chardet

with open('UTF-8.txt', 'rb') as f:
    print('UTF-8.txt')
    print(chardet.detect(f.read()))

print()
with open('Shift-JIS.txt', 'rb') as f:
    print('Shift-JIS.txt')
    print(chardet.detect(f.read()))

ファイルの文字コード、文字コードの確度、ファイルに書かれている言語を表示してくれます。

UTF-8.txt
{'encoding': 'utf-8', 'confidence': 0.9690625, 'language': ''}

Shift-JIS.txt
{'encoding': 'Windows-1252', 'confidence': 0.73, 'language': ''}

UTF-8のファイルは判別できていますが、Shift-JISのファイルは間違った文字コードとして判別しています。 bytesの内容から判別を行っているようですがbytesの元となるテキストファイルの内容によっては うまく判別できないようです。

青空文庫(夏目漱石の「こころ」)のファイルを利用してテストしてみたところ正常にUTF-8とShift-JISと判別できました。

import chardet

# 文字コードUTF-8の「こころ」テキストファイル
with open('kokoro_UTF-8.txt', 'rb') as f:
    print('kokoro_UTF-8.txt')
    print(chardet.detect(f.read()))

print()

# 文字コードShift-JISの「こころ」テキストファイル
with open('kokoro_Shift-JIS.txt', 'rb') as f:
    print('kokoro_Shift-JIS.txt')
    print(chardet.detect(f.read()))
kokoro_UTF-8.txt
{'encoding': 'utf-8', 'confidence': 0.99, 'language': ''}

kokoro_Shift-JIS.txt
{'encoding': 'SHIFT_JIS', 'confidence': 0.99, 'language': 'Japanese'}</pre>

文字コードを判別してからテキストファイルを開く
#

chardetのマニュアルに複数のファイルの文字コードを判別する方法が掲載されています。
こちらのコードを応用して、事前に文字コードを判別してからテキストファイルを開いてみます。

import glob
from chardet.universaldetector import UniversalDetector


def detect_character_code(pathname):
    """
    pathnameから該当するファイルの文字コードを判別して
    ファイル名と文字コードのdictを返す

    :param pathname: 文字コードを判別したいフォルダ
    :return: ファイル名がキー、文字コードが値のdict
    """
    files_code_dic = {}
    detector = UniversalDetector()
    for file in glob.glob(pathname):
        with open(file, 'rb') as f:
            detector.reset()
            for line in f.readlines():
                detector.feed(line)
                if detector.done:
                    break
            detector.close()
            files_code_dic[file] = detector.result['encoding']
    return files_code_dic


if __name__ == '__main__':
    # カレントフォルダ内のテキストファイルの文字コードを判別
    path = './'
    filename = '*'
    extension = 'txt'
    pathname = path + filename + '.' + extension
    files_code = detect_character_code(pathname)
    for filename in glob.glob(pathname):
        with open(filename, encoding=files_code[filename]) as f:
            for line in f.readlines():
                print(filename)
                print(line)
                break

コードを動かすとカレントフォルダ内のテキストファイルの文字コードを判別してからテキストファイルを開きます。 開いたファイルの名前と、ファイルの内容の1行目を表示します。

.\kokoro_Shift-JIS.txt
こころ

.\kokoro_UTF-8.txt
こころ

chardetは非常に便利ですが、ファイルの内容によっては文字コードを誤認識する可能性があります。 文字コードの確度が低い場合は、手動で文字コードを指定してからファイルを読み込む必要がでてきます。

関連記事

【Python】keras-yolo3を使用して物体検出
·3 分
Programming Python
Anacondaで作成した仮想環境をJupyter NotebookのKernelに追加する
·2 分
Programming Python Jupyter Notebook
Windows10にTensorFlow GPUとKerasをインストールする
·4 分
Programming Python Keras Tensorflow