さて、進みが異常に遅い気がするが、UTF-8-MAC Encodingの問題について書いてみる。

ここまでのあらすじは以下の通り。
(詳しくは【第396回】「ものかのさん囲んでUnicode正規化について聞く会」を参照のこと。)
・コンピューターはファイルシステムによってエンコーディングが違う
・MacはUTF-8(ただし変形されたものである。後述)を使っているが、NFKD正規化ということを行っている

★(書いてすぐに追記)ファイルシステムのエンコーディングはUTF-16だそうです。ご指摘ありがとうございます。下の方の実験は、ぼくがMacのターミナルのbashのlocaleをUTF-8にしているから、UTF-8のコードがlsコマンドで帰ってきているということらしいです。訂正してお詫びします。

・具体的に言うと、が(U+304C)というファイル名を作ると、か(U+304B)+゛(U+3099)になる
・これを分解(decomposition)と言う
(上には便宜上に独立した濁点を書いたが、本来は結合用濁点)
・これは「か1」<「が1」<「か2」<「が2」のようにファイル名がソートされるため

・さて、神(U+795E)の旧字体で神(U+FA19)という字がある
(便宜上U+795Eは「神(ネ申)」、U+FA19は「神(示申)」と書き分ける)
・神(示申)は、NFKD正規化を行うと、が神(ネ申)になる。
・字が変わってしまうわけで、滅茶苦茶である。
・「か(U+304B)+゛(U+3099)」であれば、もとは「が(U+304C)」であったと察しがつく。
・しかし、神(示申)が神(ネ申)になったら、その神(ネ申)はもともと神(示申)だったのか、もともと神(ネ申)であったのか手がかりがない(情報が欠損する)から、元に戻せない
・これは、Unicode(NFKD)の不具合、バグである(???)

・Macで「神1」<「神2」<「神3」<「神4」というファイルを作ると、ちゃんと4つのファイルができ、かつ、左のようなソート順になる。
・このソート順はNFKDを意識している。
(神(示申)と神(ネ申)は「実は」同じ字であることを意識している。)
・つまり、ユーザーへの見え方としてはNFKDせず、ファイルをソートするようなバックエンドではNFKDしている(???)
(なお、神(示申)と神(ネ申)は、もともと違う字であったことをソート時も意識しているようである。というのは、
  「神1」<「神2」<「神2」<「神2」
 と言う風に、神(示申)と神(ネ申)の違い以外は同じファイル名のファイルを作ると、同じフォルダ内であってもファイルはちゃんと作成され(同じ名前だと怒られず)、上のように神(ネ申)が神(示申)の前に並ぶようなソートを行うからである)
kamisort

・もう1字、冬(U+51AC)の異体字として冬(U+2F81A)というのがある。
(便宜上U+51ACは「冬(冬ニ)」、U+2F81Aは「冬(冬ン)」と書き分ける)
(冬(冬ン)はBMP外のSIPに属する(俗に言うところのサロゲート領域の)字である)
・冬(冬ン)は、NFKD正規化を行うと、冬(冬ニ)になる。

・Macで「冬1」<「冬2」<「冬3」<「冬4」というファイルを作ると、ちゃんと4つのファイルが作成される、かつ、左のようなソート順になる
(ただし冬(冬ン)をファイル名に使うと、警告メッセージが出る、ファイルを移動/コピーできない、Finderから消せない(Terminalからrmで消える)などの問題がある)※危険だから自己責任で行ってください!
・神(示申)と神(ネ申)同様、ユーザーへの見え方としてはNFKDせず、ファイルをソートするようなバックエンドではNFKDしているようだ
fuyusort

・Appleの仕様としては、文字はOS XのファイルシステムHFS+の仕様で(?HFS+のOS X実装の仕様で?)UnicodeのNFDに従うが、特例として
 U+2000~U+2FFF
 U+F900~U+FAFF(神(示申)はここに入る)
 U+2F800~U+2FAFF(冬(冬ン)はここに入る)
の場合は分解対象から除外するとしている。
(これをmonokanoさん、NAOIさんに習って便宜上 Modified NFDと呼ぼう。)
http://developer.apple.com/library/mac/#qa/qa1173/_index.html
Precomposed versus Decomposed

This Q&A assumes that you're familiar with the terms precomposed and decomposed Unicode. If that's not the case, there's a short explanation in Technical Q&A QA1235, 'Converting to Precomposed Unicode'.

Important: The terms used in this Q&A, precomposed and decomposed, roughly correspond to Unicode Normal Forms C and D, respectively. However, most volume formats do not follow the exact specification for these normal forms. For example, HFS Plus (Mac OS Extended) uses a variant of Normal Form D in which U+2000 through U+2FFF, U+F900 through U+FAFF, and U+2F800 through U+2FAFF are not decomposed (this avoids problems with round trip conversions from old Mac text encodings). It's likely that your volume format has similar oddities.


・これが「が」は「か+゛」になったが、神(示申)が神(ネ申)に、冬(冬ン)が冬(冬ニ)に(見た目上)ならなかった理由でもある(AppleはFinderからみえる上においては、仕様どおりModified NFDを行っている)ようにも見えるし、ファイル名ソートのバックエンドにおいては(「冬」<「冬」<「冬1」<「冬1」となる以上)この2つを「元は違うけど、同じ字としてみなす」という処理を行っているように見える。



以上、前回までのあらすじだけで、ぼくが1日にブログを書く量としてはいい感じにおなかいっぱいになってきたような気がするが、今日のお題である。

上のように、Macで、デスクトップに「foo」というフォルダを作って、その中に「が」「神」「神」「神2」「神2」「冬」「冬」というフォルダーを作ってみた。
foo

で、これを、lsコマンドでターミナルに表示してみると、なぜか神(示申)も神(ネ申)も神(ネ申)に、冬(冬ニ)も冬(冬ン)も冬(冬ニ)に見える
fools

なぜか分からない。(フォントの問題ではなさそうだ。)

分からないなりに、先に進む。lsコマンドの結果をファイルにリダイレクトしてみる。

[foo]$ ls > ../fools.txt


デスクトップにfools.txtというファイルが出来ている。
CotEditorで見てみると、エンコーディングはUTF-8になっていて、冬(冬ニ)/冬(冬ン)、神(示申)/神(ネ申)もきちんと書き分けられている。
cotls

「が」は分解されているだろうか。
ターミナルでfools.txtをダンプしてみる。

[Desktop]$ od -tx1c fools.txt > fools_dump.txt


結果はファイルにリダイレクトし、CotEditorで見てみた。
fools_dump

(ネ申)は0xe7a59e、(示申)は0xefa899、(冬ニ)は0xe586ac、冬(冬ン)は0xf0afa09aと、正しいUTF-8になっている。

で、問題の「が」であるが、これは0xe3818b、0xe38299に分離している。
これは「か(U+304B)」と「゛(U+3099)」のUTF-8である。

ということで、Macのファイルの文字コードは見た目上UTF-8であって、「が」はNFDするが「神(示申)」はNFDしないことが分かった。

★(書いてすぐに追記)上にも書きましたが、MacのファイルシステムはUTF-16であって、ここでlsコマンドがUTF-8を返しているのは単にターミナルのlocaleをデフォルトのUTF-8にしているからのようです。訂正してお詫びします。ただ、Unicodeであって、一部の文字にのみNFDを掛けているという本筋は変わりません。

でも2週間でここまでって進みが遅すぎると思うの。