From: Tanaka Akira Date: 2008-07-24T05:01:56+09:00 Subject: [ruby-dev:35643] Re: non-locale filename encoding 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 は削除しませ んか? > まぁ、田中さんの指摘で気付いたのですが、 > filesystem と異なる encoding を持っているが正しいpath の string を、 > 他の FS 系の API につっこんだ場合は悩ましく、 > 引数の string を filesystem encoding に自動変換、 > または filesystem encoding と異なる場合は例外、なんてことをすると、 > Unix 系ではこのケースで悲しいことになります。 Unix のファイル名は文字列でなくバイト列なので、文字列だと思っ て扱えば無用に問題を呼び込みますね。 > 本当は dir でなく、その filesystem に > external encoding をセットしないといけないんだろうな。 これは意図がよくわかりません。 > やっと田中さんの意図した問題点が理解できました。 > ご指摘の課題は仰る通りで、確かに解決策は、 > 「無変換のパスに確度の高いエンコーディングをつけてを返す API を用意する」 > がベストでしょう。 えぇ。 > 田中さんの認識では、:external_encoding/:internal_encoding は、 > ファイルパスの変換のための機構である、となっているように思います。 はい。現時点のコードを読んだ結果、そのように思いました。 > わたしの認識では以下の通りになっています。 > :external_encoding : ファイルシステムのエンコーディングを強制的に指定する機構 > :internal_encoding : 自動変換のための機構 > なので、こちらで、 > :external_encoding : システムネイティブのエンコーディングを指定 (現在はない) > :internal_encoding : 自動変換させない > と指定すれば、 > 「無変換のパスに確度の高いエンコーディングをつけてを返す API を用意する」 > は一応実現できます。 やりたいことに対してそれは迂遠ではありませんか? それに、指定に失敗すると Dir は表示専用になってしまうわけで すよね。そんな可能性をこれみよがしに提供するのは良くないので はないでしょうか。 > ちなみに、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 に変換してしまえばいいのではないかと思っています。 -- [田中 哲][たなか あきら][Tanaka Akira]