VC9とUTF-8 (BOM付きUTF-8)と「もっとよりよく」闘うための鍋の具

VC9とutf-8 (BOM付きUTF-8)VC9とUTF-8 (BOM付きUTF-8)別解の続き、とでも言うかな。「答え合わせ」とでも言うか。

utf-8-sig ってさ、Google さんを召還すれば、いくらでも出てくるよ。Python での扱い方は。あたしのサイトのばやい、大抵裏テーマがあって、具体的には例えば「screencastが普及して欲しい」とかがあるよ。ので案外見かけ上「メインテーマ」にみえる部分に重きを置いていない場合がある。だからね、ここであえて「アタシの解」を書くことに価値があるんだろうか、とは思うわけ。

そうなんだけど、ちと個人用途でほんとに自分で「それ」をすることになったんで、ま、「解の一つ」としてあげとこうかと。そもそも「困って検索して」結果あたしのサイトにたどり着くのであろうから、まぁなんかしらの答えは持ち帰ってもらった方が気分よかろ?

何の話か? こういうこと:

  • Unix向けが主役の C++を書いている
  • コーディング規約的なことで、ソースコードは BOM なし utf-8 である必要がある
  • Windows でもビルド出来るようにしておくと、品質が高くなる(思わぬ潜在バグに気付けるので)
  • ので、簡単に utf-8-sig との行き来を出来るようにしておきたい
  • が、変更もないのにタイムスタンプが変わることは避けたい

つまりは、
VC9とutf-8 (BOM付きUTF-8)で書いた以下:

1 import codecs
2 with codecs.getwriter("utf-8-sig")(open("test3.cpp", "wb")) as fo:
3     fo.write(open("test1.cpp", "rb").read().decode("utf-8"))

の「よりちゃんとしたやつ」が欲しくね? ってハナシ。

あたしの解は以下です:

utf8conv.py
 1 class UTF8Converter(object):
 2     def __init__(self, target):
 3         if target == 'msvc':
 4             self._dest_enc = 'utf-8-sig'
 5         else:
 6             self._dest_enc = 'utf-8'
 7 
 8     def __call__(self, sf):
 9         import os
10         import codecs
11         import tempfile
12 
13         cnt_in = open(sf, "rb").read()
14         tf = tempfile.NamedTemporaryFile(delete=False)
15         with codecs.getwriter(self._dest_enc)(tf) as fo:
16             fo.write(cnt_in.decode("utf-8-sig"))
17         cnt_out = open(tf.name, "rb").read()
18         if cnt_in != cnt_out:
19             open(sf, "wb").write(cnt_out)
20         else:
21             os.unlink(tf.name)
22 
23 if __name__ == '__main__':
24     import sys
25     cnv = UTF8Converter(sys.argv[1])
26     for fn in sys.argv[2:]:
27         cnv(fn)

注意して欲しいのは、「any from-to utf-8系」 ではない ってこと。あくまでも「テキストエディタが utf-8(系)で書き出せる能力を持っていて、かつ、開発者は自覚的にutf-8(系)で書き出す」ことを前提としてるってこと。ので、utf-8 以外を与えれば当然 Unicode 例外起こります。


ところでこれ、例によってというか。10分で書き上げるつもりが、なぜか1時間以上かかってしまった。つまらんことでミスって。あたしってばいつもそうだ ;)