From: "NARUSE, Yui" Date: 2008-07-25T01:43:42+09:00 Subject: [ruby-dev:35652] Re: non-locale filename encoding Tanaka Akira wrote: > In article <488771FD.4020800@airemix.jp>, > "NARUSE, Yui" writes: > >> 想定としては、Unix 系でファイルシステムのエンコーディングが >> locale と異なる場合です。 >> この場合、Unix 系なのでファイルシステム上のパス文字列は変換されず、 >> その一方でファイルシステムのエンコーディングがセットされます。 >> この string を扱う force_encoding する必要があることを嫌いました。 > > なるほど。 > >> file の open の場合、 >> UTF-8 ロケールにて Shift_JIS のテキストを読む場合に、 >> open("sjis.txt"){|f| puts f.read.force_encoding("UTF-8") } >> とするのではなく、 >> open("sjis.txt", "r:sjis"){|f| puts f.read } >> とした方がスマートなのですが、これと同様に >> >> Shift_JIS ロケールにて UTF-8 なファイルシステムの場合、 >> opendir("."){|dir| puts dir.read.force_encoding("UTF-8") } >> よりも >> opendir(".", :external_encoding=>"UTF-8"){|dir| puts dir.read } >> とした方がスマートであろうと考えました。 > > 上記の例では puts しかしていません。 > そのように表示するだけであれば使用できますが、open などの操 > 作はできないわけですよね。 > > 表示しか行わないアプリケーションってどのくらいあるんでしょうか? > > Dir を表示専用にしてしまうオプションは、適切とは思えません。 > > Dir の :external_encoding と :internal_encoding は削除しませ > んか? [ruby-dev:35644] の通り、:external_encoding のみだと force_encoding になります。 :external_encoding/:inernal_encoding 方式だと、Windows 環境用に :internal_encoding が必要です。 つまり、デフォルトで locale が入っていて、ここで自動変換をしています。 むしろ、最も使われるのはこちらなのかな。 >> まぁ、田中さんの指摘で気付いたのですが、 >> filesystem と異なる encoding を持っているが正しいpath の string を、 >> 他の FS 系の API につっこんだ場合は悩ましく、 >> 引数の string を filesystem encoding に自動変換、 >> または filesystem encoding と異なる場合は例外、なんてことをすると、 >> Unix 系ではこのケースで悲しいことになります。 > > Unix のファイル名は文字列でなくバイト列なので、文字列だと思っ > て扱えば無用に問題を呼び込みますね。 あぁ、なるほど。 > それに、指定に失敗すると Dir は表示専用になってしまうわけで > すよね。そんな可能性をこれみよがしに提供するのは良くないので > はないでしょうか。 これ見よがしにならない程度には使いづらくしたつもりです、17文字ですし。 基本的には指定しなくていいはずですし。 (Unix や Mac OS X では最初から生+localeだから) >> ちなみに、Windows ファイルパスを FS に渡した場合の動作の予定を書いておくと、 >> US-ASCII、ASCII-8BIT 及び Unicode 系 -> UTF-16LE にして Unicode API に渡す >> locale -> ANSI API に渡す or UTF-16LE に変換してから Unicode API に渡す >> それ以外 -> UTF-16LEに自動変換して Unicode API or 例外 or そのまま ANSI >> >> 問題はそれ以外で、 >> 自動変換すると Microsoft CodePage 以外から変換するとマッピングの違いではまる可能性が >> 高いので MSCP でない場合か、または locale 以外では例外を出したいのですが、 >> それをやると Unix の場合で悲しい思いをするので悩ましく思っているところです。 > > Unix のファイル名はバイト列なので、string のエンコーディング > は無視してバイト列をそのまま使うべきです。エンコーディングに > よって例外にするのは反対です。 > > Windows のファイル名は文字列だと思うので、locale 以外は全部 > UTF-16LE に変換してしまえばいいのではないかと思っています。 なるほど、その区別は明快ですね。 こちらはそれで賛成です。 > ところで、Windows で :external_encoding に Unicode でも > locale でもない encoding を指定したらどうなるんですが? Windows では :external_encoding は Unicode 系のみですかね。 「Windows のファイル名は文字列」というのは、Unicode 文字の事でしょうから。 Unicode 以外の :external_encoding だと例外でいいのかな。 Windows のファイル名がバイト列になるケースがもし存在するならば必要なのでしょうが、 以前の samba の話等の感じでは必要なさそうでしたし。 -- NARUSE, Yui