2012年12月7日金曜日


Windows の unicode と MAX_PATH

3年前だったか、仕事で付き合いのある人で変わった癖(?)のある人に出会った。
その人、自分でフォルダ名(ファイル名も)を付ける際に異常なほど長い名前を付けていた。
理由は、

「だってほら、一目で何のフォルダ(ファイル)か分かるでしょ?」

一目でっつっても、ファイル名が日本語の summary になっていた。
しかもご丁寧にどのファイルにも作成日が先頭に付いている。
もっと厄介なのは、どのファイル(フォルダも)も、何処に移動しても重複しないように意図されていたこと。
例えば年度フォルダなど、「2012」や「H24」といった簡素なものはまず無く、その親フォルダ名が頭に付いていたりする。
そら長くなるわ。
て言うか、階層の意味ねーじゃん、て言いたくなった。

だが人それぞれ。
毛の抜けたSEもいれば、毛の抜けたアンガス・ヤングもいる。

先日その人から連絡があった。
「毛の抜けたSEさんに影響されて、ちょっと前にプログラミングの勉強を始めた。。。」
ふむふむ。で?、まさか教えろとか言わねーよな。

「MAX_PATH って260バイトですよね?
 おかしいんですよ、400バイト超えてるんですけど平気なんです。」

別に私は貴方のファイルパスが260バイトを超えようが、3バイトに満たなくても平気ですけど。
っつーか、MAX_PATH ってまさか「C」やってるって言わねーよな!

「ご多分に漏れず C# です」

ブライアン・ジョンソンのように高音のしわがれ声で
「#?@! You!!!」
電話を切りたくなったが、ちょっと待てよ。

400バイトってどういう勘定してるんだ?

「だってほら、私が付けるファイル名は殆ど日本語の全角文字だから、
 単純に×2すると400バイトをゆうに超えるんですよ。」

ここにも居たか、shift-jis にしがみつく過去の遺物が。
かくいう私も、しがみつかざるを得ない状況なのだが。。。


今の Windows は内部では UNICODE (UTF-16) を使用している。

これは、全ての文字を2バイトで表現しようとするものだが、
世界中の文字が、たった 65,536 通りで表現できるはずもない。
よって、通常これだけあれば大丈夫だろうと思われる文字群を、
基本多言語面(BMP)という領域に収め、それ以外をサロゲートペアという
2つの2バイト域(計4バイト)で表現する。
つまり、通常2バイトだが、文字によっては4バイト使用する文字もあるということ。

もちろんこの人は、UNICODE の話をしているのではない。
shift-jis の話をしているのだ。だから「全角」という言葉が出てくる。

だが、ちょっと怖くなったので、今回改めてネットで検索してみたら、

やっぱり!

昔の shift-jis の頃に作成されたであろうページがわんさかヒットする。
それらのページの多くには、

「Windows の最大ファイルパス長は 260バイト

だが、新設なページも多数あった。

「Windows の最大ファイルパス長は 260バイト(UNICODE は260文字)」

そう、UNICODE では、206文字なのだ。
だから、

「あいうえお」と「aiueo」は同じ文字数の5文字だ。

shift-jis の世界では「あいうえお」は確かに10バイトだが、
UNICODE でも「あいうえお」はおそらく10バイトだろう。
ただし、「aiueo」は shift-jis では5バイトだが、
UNICODE では10バイトだ。

UNICODE は先にも言ったように、通常2バイトだから、変な漢字(失礼)や特殊な文字を使用していなければ、バイト数計算は楽だ。
だが、最大パス長を示す _MAX_PATH 定数が持つ「260」という数字は、

shift-jis の世界ならバイト数
UNICODE の世界なら文字数

という切り分けをしないといけない。
が、現在ではあまり意識しなくても良い環境になっている。

というのも、Java も C# も VB.NET も、て言うか Visual Studio も、
C++Builder も Delphi もすべて内部では UNICODE になっている。
Windows も UNICODE なんだから何も考えずに「文字数」でいけばいい。

ただし、ファイルを開いたり、保存したりするときは、文字コードに気をつけるのは言わずもがな、である。

あっ!あともう一つ。
USBメモリは良く使うが、NTFS でフォーマットできなかったりする。
確か、Windows日本語版は FAT には shift-jis に変換して送信するはず。
これはファイルの中身の話ではない。ファイル名の話だ。
だから上記の400バイト(実際は200文字以下だろう)を超えるパス長の状態そのままで、USBメモリにコピーするとエラーになる可能性がある。


しかし今や「全角」「半角」という言葉自体が消滅しつつあるのを、先に勉強した方が良い。
それを踏まえて「全角」「半角」という言葉を使って欲しい。

それと、「260」と言ったが、正確には「259」文字だ。
文字列の最後に null が付くので。

また、パス文字列の前に接頭辞として "\\?\" を付けると、約32,000文字までいけるらしいが、
そもそも最大パス長付近をウロウロしているようでは、まだまだフサフサだな。

0 件のコメント:

コメントを投稿