ファイル読み書きを学ぼう。以下のサンプルはすべてpython 2.5対応で、python3には対応してない。
まず前回も示したファイルの書き出し方
# -*- coding:utf-8 -*- text_ucs = u"あいうウェブABC言語\n" f = open('a.txt', 'wb') f.write(text_ucs.encode('utf-8')) f.close()
これを実行すると、a.txt が生成される。中身は UTF-8の文字コード。
次にこれを読み込む。
# -*- coding:utf-8 -*- from types import * import re # ファイル読み込み f = open('a.txt', 'rb') content_str = f.read() f.close() # 念のためファイルのタイプを確認 print(str(type(content_str))) #<type 'str'> # ファイルの中身をUnicode文字列に変換 content_ucs = unicode(content_str, 'utf-8') print(str(type(content_ucs))) #<type 'unicode'> # ファイルの中身を処理 content_ucs = re.sub(ur'あ', ur'わ', ucs) # 念のためファイルの中身を確認 print(content_ucs.encode('utf-8')) # ファイル書き出し f = open('a2.txt', 'wb') f.write(content_ucs.encode('utf-8')) f.close()
openの引数 'rb' は読み込みモード r 、バイナリ読み込み(改行変換なし) b という意味。
変数 content_str にはファイルの中身すべてが入る。
このときcontent_strの型はstr型だ。
中身を文字として処理したいならすぐにUnicode文字列に変換しておこう。
unicode(content, 'utf-8') のところで変数content_strをUnicode型文字列に変換だ。
unicode(content_str, 'utf-8')の utf-8 はなんだろう? unicodeなんだからUTF-8に変換するのは当たり前のような
それは変換先の文字コードではなくて(変換後の文字コードはunicodeつまりUCS2に決まってるからね)、変換前の文字コードは何かを指示してる。今回読み込もうとするファイルはUTF-8だっただろ。
もしWindowsのShift_JISで書かれていたテキストファイルを読み込むなら
変換前の文字コードに cp932 を指定すればいい。つまり
ucs = unicode(content_str, 'cp932')
と書けばいいね。
Shift_JISなのに cp932?
Shift_JISというのはJISの規格で、cp932というのはWindowsで使えるShift_JISの亜種だよ。
具体的な差はこちらで見れる。
http://charset.uic.jp/compare/cp932/shift_jis/bold/
実際のところWindowsで使われてるcp932のほうが重要だ。
文字コードに亜種とかあるのか‥
ほかにも EUC-JP の亜種には eucJP-ms と CP51932 という2つがあるよ。WindowsのInternetExplorerで書き込んだ文字列をEUC-JPで保存すると CP51932 という文字コードになるんだ。
http://www.iana.org/assignments/charset-reg/CP51932
http://legacy-encoding.sourceforge.jp/wiki/
を見ると、Pythonは cp51932 に未対応。いっぽう PHP,Rubyは標準で対応。Perlは拡張モジュールで対応。
Pythonは日本語に関しては他の言語より強くないんだな‥。使う人の多いPHPは強いね。
UTF-8にもWindows亜種があるの?
UTF-8はさすがに統一されている。亜種はないよ。しかし「〜」をWindowsで入力するとU+FF5Eになるのに、LinuxだとU+301Cになるとか、文字遣いの違いはある。
ところで Python2.5では withというStatementが使えるようになった。
使うと次のように f.close()を書かなくても自動で実行してくれるようになる。
上のスクリプトを書き直し
# -*- coding:utf-8 -*- from __future__ import with_statement import re with open('a.txt', 'rb') as f: content_str = f.read() content_ucs = unicode(content_str, 'utf-8') content_ucs = re.sub(ur'あ', ur'わ', content_ucs) with open('a2.txt', 'wb') as f: f.write(content_ucs.encode('utf-8'))
変数content_strがインデントの中で宣言されてるけど、これ変数の有効範囲(スコープ)はインデントの外も含むの?
PythonはPHPやJavaScriptと同じで、インデントブロック(C/Javaでいう { }
)の中と外でスコープが違わない。
関数の中と外でスコープを区切られる。あとファイル単位でスコープが区切られる。
上のサンプルは関数の外なので、グローバルスコープつまりグローバル変数扱い。