読者です 読者をやめる 読者になる 読者になる

テキストファイルで使用されている文字コードを目視で確認する

python

呼称: 文字コード指定によるファイルオープン
目的: テキストファイルで使用されている文字コードを判別する
特徴: Python がサポートしている文字コードを全て試せる
用例: テキストファイルがどの文字コードを使用しているか分からないときに使用する
備考: 例外処理が冗長なのは python2.4 以下の互換性対応

最も精度の高い文字コードの判別処理を実装してみました(^ ^;;
対象とするテキストファイルの特性を考慮して read_line_num や supprt_charset を変更すると良いです。バッチ系の処理では、文字コード判別ライブラリを使用すると思いますが、それでは正常に判別できなかったファイルに対してのリカバリ処理で有用かなと思います。EUC-JP と EUC-CN 等は(テキストが少ないと)自動判別が難しいそうです。

#!/usr/bin/env python
# -*- coding: utf-8 -*-

import codecs
import os
import sys

read_line_num = 5
support_charset = [
    'shift_jis',
    'euc_jp',
    'iso2022_jp',
    'utf-8',
    'iso8859_1',
    'iso8859_5',
    'iso8859_9',
    'koi8_r',
    'koi8_u',
    'gb18030',
    'euc_kr',
    'big5',
]

class Null(object):
    """NULL オブジェクト"""
    def __new__(cls, *args, **kwargs):  # Singleton for 1 instance
        if '_inst' not in vars(cls):
            cls._inst = super(Null, cls).__new__(cls, *args, **kwargs)
        return cls._inst
    def __init__(self, *args, **kwargs): pass
    def __call__(self, *args, **kwargs): return self
    def __repr__(self): return 'Null()'
    def __iter__(self): return iter(())
    def __nonzero__(self): return False
    def __getattr__(self, name): return self
    def __setattr__(self, name): return self
    def __delattr__(self, name): return self

def main():
    """Script Main"""
    target_file = sys.argv[1:]
    for file in target_file:
        content = get_content_with_various_charset(file)
        print '*'*10, file, '*'*10
        for key, value in content.items():
            print key, value

def open_file(file, charset):
    """ファイルをオープンしてファイル識別子を返す
    失敗したときは Null オブジェクトを返す
    """
    fp = Null()
    if os.access(file, os.R_OK):
        try:
            fp = codecs.open(file, encoding=charset, mode='r')
        except IOError, err:
            pass
    return fp

def get_content_with_various_charset(file):
    """対応文字コードを指定してファイルを開いて
    最初の数行のテキストを返す"""
    text, content = '', {}
    for charset in support_charset:
        text, line_num = '', 0
        fp = open_file(file, charset)
        try:
            try:
                for line in fp:
                    line_num +=1
                    text += line
                    if line_num == read_line_num:
                        break
                content[charset] = text
            except Exception, err:
                pass
        finally:
            fp.close()
    return content

if __name__ == '__main__':
    main()

実行結果。

$ python open_with_various_charset.py sjis.txt eucjp.txt utf8.txt 
 ********** sjis.txt **********
gb18030 丂丂戞擇栭

丂偙傫側柌傪尒偨丅
丂榓彯偺幒傪戅偑偭祹丄楲壓揱偄偵帺暘偺晹壆傊婣傞偲峴摂偑傏傫傗傝揰偭祹偄傞丅
曅旼傪嵗姉抍偺忋偵撍偄祹丄摂怱傪憕偒棫祹偨偲偒丄壴偺傛祥側挌巕偑傁偨傝偲

koi8_r │@│@▒Ф⌠Я√И

│@┌╠┌Я┌х√╡┌П▄╘┌╫│B
│@≤a▐╝┌л▌╨┌П▒ч┌╙┌а┌д│A≤L┴╨⌠`┌╒┌и▌╘∙╙┌л∙■┴╝┌ж▀A┌И┌ф█s⌠■┌╙┌з┌Я┌Б┌Х⌠_┌а┌д┌╒┌И│B
∙п∙G┌П█ю┼≈▓c┌л▐Ц┌и⌠к┌╒┌д│A⌠■░S┌П▒~┌╚≈╖┌д┌╫┌ф┌╚│A┴т┌л┌Ф┌╓┌х▓ ▌q┌╙┌о┌╫┌Х┌ф

shift_jis   第二夜

 こんな夢を見た。
 和尚の室を退がって、廊下伝いに自分の部屋へ帰ると行灯がぼんやり点っている。
片膝を座蒲団の上に突いて、灯心を掻き立てたとき、花のような丁子がぱたりと

iso8859_9 @@‘æ“ñ–é

@‚±‚ñ‚È–²‚ğŒ©‚½B
@˜a®‚ÌŽº‚ğ‘Ş‚ª‚Á‚āA˜L‰º“`‚¢‚ÉŽ©•ª‚Ì•”‰®‚Ö‹A‚é‚ƍs“”‚ª‚Ú‚ñ‚â‚è“_‚Á‚Ä‚¢‚éB
•Ğ•G‚ğÀŠ—’c‚̏ã‚É“Ë‚¢‚āA“”S‚ğ‘~‚«—§‚Ä‚½‚Æ‚«A‰Ô‚̂悤‚È’šŽq‚ª‚Ï‚½‚è‚Æ

koi8_u │@│@▒Ф⌠Я√И

│@┌╠┌Я┌х√╡┌П▄╘┌Ґ│B
│@≤a▐╝┌л▌╨┌П▒ч┌╙┌а┌д│A≤L┴╨⌠`┌╒┌и▌╘∙╙┌л∙■┴╝┌ж▀A┌И┌ф█s⌠■┌╙┌з┌Я┌Б┌Х⌠_┌а┌д┌╒┌И│B
∙п∙G┌П█ю┼≈▓c┌л▐Ц┌и⌠к┌╒┌д│A⌠■░S┌П▒~┌╚≈ї┌д┌Ґ┌ф┌╚│A┴т┌л┌Ф┌є┌х▓ ▌q┌╙┌о┌Ґ┌Х┌ф

iso8859_5 @@‘ц“ё–щ

@‚Б‚ё‚Ш–В‚№ŒЉ‚НB
@˜aЎ‚ЬŽК‚№‘о‚Њ‚С‚ФA˜L‰К“`‚Ђ‚ЩŽЉ•Њ‚Ь•”‰Ў‚ж‹A‚щ‚Цs“”‚Њ‚к‚ё‚т‚ш“_‚С‚Ф‚Ђ‚щB
•а•G‚№РŠ—’c‚Ьу‚Щ“Ы‚Ђ‚ФA“”S‚№‘~‚Ћ—Ї‚Ф‚Н‚Ц‚ЋA‰д‚Ь‚ц‚Є‚Ш’šŽq‚Њ‚Я‚Н‚ш‚Ц

iso8859_1 @@‘æ“ñ–é

@‚±‚ñ‚È–²‚ðŒ©‚½B
@˜a®‚ÌŽº‚ð‘Þ‚ª‚Á‚āA˜L‰º“`‚¢‚ÉŽ©•ª‚Ì•”‰®‚Ö‹A‚é‚ƍs“”‚ª‚Ú‚ñ‚â‚è“_‚Á‚Ä‚¢‚éB
•Ð•G‚ðÀŠ—’c‚̏ã‚É“Ë‚¢‚āA“”S‚ð‘~‚«—§‚Ä‚½‚Æ‚«A‰Ô‚̂悤‚È’šŽq‚ª‚Ï‚½‚è‚Æ

 ********** eucjp.txt **********
koi8_r ║║║║бХ╩╟лК

║║╓Ё╓С╓йл╢╓Р╦╚╓©║ё
║║о╩╓д╓к╓й╓К╩р╤║╓РиИ╓ц╓ф╓К║ё╓©╓╥╓╚╓к╪╚й╛╓н╩р╓г╓╒╓К║ё╓©╓юит╩в╣д╓й╩Ж╓к╓о
╓╓╓д╓н╢ж╓к╓╚╢Ц╓╛ды╓Л╓ф║╒юдк╥╪Г╓к╓й╓ц╓ф╓╓╓К║ё╪╚й╛╓╛╦Фа╟╓н╢Ц╓о╓╓╓дды╓Л╓©╓н╓╚╓╓

gb18030   妈话屉

 こんな檀を斧た。
 匣つになる灰丁を砷ってる。たしかに极尸の灰である。ただ稍蛔的な祸には
いつの粗にか淬が馁れて、滥朔肩になっている。极尸が告涟の淬はいつ馁れたのかい

big5 ﹛﹛鎔趕歾

﹛仇氏卅抴毛葦凶﹝
﹛牰勾卞卅月閡間毛扙勻化月﹝凶仄井卞憤坌及閡匹丐月﹝凶分尕閤腔卅儀卞反
中勾及棉卞井氬互囁木化﹜斂侇潛卞卅勻化中月﹝憤坌互豢蟆及氬反中勾囁木凶及井中

euc_jp   第三夜

 こんな夢を見た。
 六つになる子供を負ってる。たしかに自分の子である。ただ不思議な事には
いつの間にか眼が潰れて、青坊主になっている。自分が御前の眼はいつ潰れたのかい

iso8859_9 ¡¡¡¡Âè»°Ìë

¡¡¤³¤ó¤ÊÌ´¤ò¸«¤¿¡£
¡¡Ï»¤Ä¤Ë¤Ê¤ë»Ò¶¡¤òÉé¤Ã¤Æ¤ë¡£¤¿¤·¤«¤Ë¼«Ê¬¤Î»Ò¤Ç¤¢¤ë¡£¤¿¤ÀÉԻ׵Ĥʻö¤Ë¤Ï
¤¤¤Ä¤Î´Ö¤Ë¤«´ã¤¬ÄÙ¤ì¤Æ¡¢ÀÄË·¼ç¤Ë¤Ê¤Ã¤Æ¤¤¤ë¡£¼«Ê¬¤¬¸æÁ°¤Î´ã¤Ï¤¤¤ÄÄ٤줿¤Î¤«¤¤

koi8_u ║║║║бХ╩╟лК

║║єЁєСєйлЄєР╦╚є©║ё
║║о╩єдєкєйєК╩рІ║єРиИєцєфєК║ёє©єЇє╚єк╪╚й╛єн╩рєгє╒єК║ёє©єюит╩в╣дєй╩Жєкєо
єєєдєнЄжєкє╚ЄЦє╛дыєЛєф║╒юдкЇ╪ГєкєйєцєфєєєК║ё╪╚й╛є╛╦Фа╟єнЄЦєоєєєддыєЛє©єнє╚єє

iso8859_5 ЁЁЁЁТшЛАЬы

ЁЁЄГЄѓЄЪЬДЄђИЋЄПЁЃ
ЁЁЯЛЄФЄЫЄЪЄыЛвЖЁЄђЩщЄУЄЦЄыЁЃЄПЄЗЄЋЄЫМЋЪЌЄЮЛвЄЧЄЂЄыЁЃЄПЄРЩдЛзЕФЄЪЛіЄЫЄЯ
ЄЄЄФЄЮДжЄЫЄЋДуЄЌФйЄьЄЦЁЂРФЫЗМчЄЫЄЪЄУЄЦЄЄЄыЁЃМЋЪЌЄЌИцСАЄЮДуЄЯЄЄЄФФйЄьЄПЄЮЄЋЄЄ

iso8859_1 ¡¡¡¡Âè»°Ìë

¡¡¤³¤ó¤ÊÌ´¤ò¸«¤¿¡£
¡¡Ï»¤Ä¤Ë¤Ê¤ë»Ò¶¡¤òÉé¤Ã¤Æ¤ë¡£¤¿¤·¤«¤Ë¼«Ê¬¤Î»Ò¤Ç¤¢¤ë¡£¤¿¤ÀÉԻ׵Ĥʻö¤Ë¤Ï
¤¤¤Ä¤Î´Ö¤Ë¤«´ã¤¬ÄÙ¤ì¤Æ¡¢ÀÄË·¼ç¤Ë¤Ê¤Ã¤Æ¤¤¤ë¡£¼«Ê¬¤¬¸æÁ°¤Î´ã¤Ï¤¤¤ÄÄ٤줿¤Î¤«¤¤

 ********** utf8.txt **********
koi8_r Ц──Ц──Г╛╛Е⌡⌡Е╓°

Ц──Е╨┐Ц│└Е°÷И√⌠Ц│╝Г°÷Д╦╜Ц│╚Ф╤╪Ц│©Е▐╟Ц│╝Ц┌┬Ц│├Ц│╙Ц┌┌Ц│╝Ц┌▓Ф█╝Ц│┬Ц│╕Ц─│Ц│²Ц│╝Е▒╗Е⌡╡Ц│╚Е╟▐Ц│∙Ц│└Е╨┼Е┤═Ц│▄Д╦╕Ц│╧Ц│╕Ц│┌Ц┌▀Ц─┌
Е▐╟Ц│╞И╩▓Е┘┴Ц┌┼Ц│╚Е┘┴Ц│ёЦ│╕Ц│└Ц┌▀Ц─┌Г┴┤И ┘Ц│╚Ц│╞Е⌡⌡Х╖▓Ц│╙Х├ЁЦ┌▓Е┴█Ц│╚Г╫╝Ц│└Ц│╕Г┬╨Ц│∙Ц┌⌠Ц│▄Д╦─Д╨╨Ц│╖И┘▓Ц┌▓Иё╡Ц┌⌠Ц│╖Ц│└Ц┌▀Ц─┌
Х┌╢Ц│╞Г┘╝Ц│≈Ц┌│Ц┌┴Ц│≈Ц│└Ц─┌

iso8859_9   第四夜

 広い土間の真中に涼み台のようなものを据えて、その周囲に小さい床几が並べてある。
台は黒光りにå…
utf-8   第四夜

 広い土間の真中に涼み台のようなものを据えて、その周囲に小さい床几が並べてある。
台は黒光りに光っている。片隅には四角な膳を前に置いて爺さんが一人で酒を飲んでいる。
肴は煮しめらしい。

koi8_u Ц──Ц──Г╛╛Е⌡⌡Еє°

Ц──Е╨┐Ц│└Е°÷И√⌠Ц│╝Г°÷Д╦ґЦ│╚ФІ╪Ц│©Е▐╟Ц│╝Ц┌┬Ц│├Ц│╙Ц┌┌Ц│╝Ц┌▓Ф█╝Ц│┬Ц│іЦ─│Ц│²Ц│╝Е▒╗Е⌡╡Ц│╚Е╟▐Ц│∙Ц│└Е╨┼Е┤═Ц│▄Д╦іЦ│╧Ц│іЦ│┌Ц┌▀Ц─┌
Е▐╟Ц│╞И╩▓Е┘┴Ц┌┼Ц│╚Е┘┴Ц│ёЦ│іЦ│└Ц┌▀Ц─┌Г┴┤И ┘Ц│╚Ц│╞Е⌡⌡Хї▓Ц│╙Х├ЁЦ┌▓Е┴█Ц│╚ГҐ╝Ц│└Ц│іГ┬╨Ц│∙Ц┌⌠Ц│▄Д╦─Д╨╨Ц│їИ┘▓Ц┌▓Иё╡Ц┌⌠Ц│їЦ│└Ц┌▀Ц─┌
Х┌ЄЦ│╞Г┘╝Ц│≈Ц┌│Ц┌┴Ц│≈Ц│└Ц─┌

iso8859_5 у€€у€€чЌЌх››хЄœ

у€€хКƒу„хœŸщ–“уЎчœŸфИ­уЋцЖМуПхАуЎу‚ˆу†уЊу‚‚уЎу‚’цЎуˆуІу€ууЎх‘Јх›ВуЋхАу•у„хКŠх‡ уŒфИІуЙуІу‚у‚‹у€‚
хАуЏщЛ’х…‰у‚ŠуЋх…
iso8859_1   第四夜

 広い土間の真中に涼み台のようなものを据えて、その周囲に小さい床几が並べてある。
台は黒光りにå…

リファレンス:
http://www.python.jp/doc/release/lib/module-codecs.html
Python でUTF-8, shift_jis, euc_jpなど日本語を使う方法
Pythonの例外とその処理に関する覚え書き(概要、書式、後始末処理) - 試験運用中なLinux備忘録