diary/Kojima

・「〜」の文字コード

Windowsな環境で作ったアーカイブファイルをPlamoな環境で開いた場合、ファイル名の文字コードはだいたい問題なくEUC-JPに変換されるのだけど、 たまに "〜” がおかしい場合があるので少し調べてみた。

結構イヤらしいのは、KDEのKonsoleやgnome-terminal, XfceのTerminal上だと問題なく"〜”が表示されるけど、 EmacsやFD経由だとうまく表示されない、という環境依存なところ。

例えば、この a と b というファイルは、上記問題のないターミナル上だと同じに表示される

% cat a
A〜B
C〜D
% cat b
A〜B
C〜D

ところが、Emacsで開くと、ファイル a の"〜”は正しく表示できない

emacs.png

何が違うんだろう、、としばらく調べてみたところ、hexdump -C で見ると文字コードが違っていることがわかった。

% hexdump -C a
00000000  41 8f a2 b7 42 0a 43 8f  a2 b7 44 0a              |A...B.C...D.|
0000000c
% hexdump -C b
00000000  41 a1 c1 42 0a 43 a1 c1  44 0a                    |A..B.C..D.|
0000000a

これで見ると、ファイル b の "〜" は a1c1 という正しい euc-jp のコードになっているのに対して、 ファイル a の "〜" は、同じ "〜”に見えるものの、8f a2 b7 というコードになっているらしい。

この 8f a2 b7 というシーケンスが、なぜ "〜" になるのかはあれこれ調べてみたけどよく分からない。

8f は JIS X 0211のC1集合のss3(Single Shift 3)かな、と思うが、Shift-JIS でも EUC-JP でも
UTF-8 でも a2 b7 なんてコードは無さげなのだが、Konsoleとかgnome-terminal、Terminalが同じ
結果を示しているのを見ると、何らかのルールは決まってそうな印象

識者の目に触れることを期待して、このあたりに晒しておこう :-)

この結果を見る限り、8f a2 b7 というシーケンスは nkf が認識する(= 広く一般に使われている)コードとは違っていて、 それらを素で通したらkonsole等のターミナルが"〜"にしているような印象。ktermでは対応していないようなので、gtk+とか Qtのレベルなのかなぁ?-- kojima 2010-08-24 (火) 19:43:02

#! /usr/bin/python
# -*- coding: euc-jp -*-;

import  sys

def main():
    file = sys.argv[1]
    f = open(file, "r")
    lines = f.readlines()
    for line in lines:
        print "before:", line
        t = line.decode('euc-jp')
        print "after :", t
        tt = t.encode('euc-jp').replace("~", "〜")
        print "convd :", tt 
 
if ( __name__ == "__main__" ):
    main()

Emacs 上ではこういう結果になった。

% ./test.py  a
before: A□B

after : A~B 

convd : A〜B

before: C□D

after : C~D

convd : C〜D

この結果を見ると、Pythonの世界で 8f a2 b7 というシークエンスを EUC-JP として decode するとUTF的には普通のチルダ(~) になって、その状態で"~"を"〜"に変換して EUC-JP に encode してやれば本来のコードになるみたい

hexdump で見ても、

% ./test.py  a | hexdump -C
00000000  62 65 66 6f 72 65 3a 20  41 8f a2 b7 42 0a 0a 61  |before: A...B..a|
00000010  66 74 65 72 20 3a 20 41  7e 42 0a 0a 63 6f 6e 76  |fter : A~B..conv|
00000020  64 20 3a 20 41 a1 c1 42  0a 0a 62 65 66 6f 72 65  |d : A..B..before|
00000030  3a 20 43 8f a2 b7 44 0a  0a 61 66 74 65 72 20 3a  |: C...D..after :|
00000040  20 43 7e 44 0a 0a 63 6f  6e 76 64 20 3a 20 43 a1  | C~D..convd : C.|
00000050  c1 44 0a 0a                                       |.D..|
00000054

ということで、初期状態は 8f a2 b7 が、euc-jp -> UTF8 すると 7e になって、UTF8の世界で s/~/〜/して euc-jpに戻すと a1 c1 になる、みたい。

とりあえず当初の目的だった 8f a2 b7 というコードを持ったファイル名を修正する方法はメドが立ったけど、 8f a2 b7 というシークエンスがgtk/Qtな世界だとeuc-jpの"〜"に解釈されるのはなぜか、というあたりはよく分からんし、 そもそもWindowsな世界で作ったファイル名がEUC-JPの世界で 8f a2 b7 になる、というのがよく分からんなぁ? -- kojima 2010-08-24 (火) 20:08:47

tt = t.encode('euc-jp').replace("~", "〜")

としてたけど、これは "〜" が euc-jp な世界なので、そっちに移す余計な処理が入るから、

tt = t.replace("~", u'〜')

の方が正しいか。-- kojima 2010-08-24 (火) 21:59:15



添付ファイル: fileemacs.png 205件 [詳細]

トップ   編集 凍結 差分 バックアップ 添付 複製 名前変更 リロード   新規 一覧 検索 最終更新   ヘルプ   最終更新のRSS
Last-modified: 2021-12-17 (金) 16:35:42