Ruby on WindowsのFAQシリーズ
初学者からよく聞く
p "日本語"
p ["日本語"]
p "日本語": :"日本語"
が
"\u65E5\u672C\u8A9E"
["\u65E5\u672C\u8A9E"]
{:"\u65E5\u672C\u8A9E"=>:"\u65E5\u672C\u8A9E"}
となる問題です。
ちなみに脳筋回答
コンソールに日本語表示させる必要なんて無いんじゃない?
(割と真面目に、Rubyのp
による日本語表示をwindowsでやる必要は無いと思ってます)
真面目回答
出力が真の意味で文字化けする危険性があるが
スクリプトの頭に
Encoding.default_internal = __ENCODING__
付けとけ
p "日本語"とは?
引数を人間に読みやすい形に整形して改行と順番に標準出力 $stdout に出力します。主にデバッグに使用します。
引数の inspect メソッドの返り値と改行を順番に出力します。つまり以下のコードと同じです。
print arg[0].inspect, "\n", arg[1].inspect, "\n", ...
つまり、p("日本語")
はputs "日本語".inspect
となります。
p "日本語".encoding # => #<Encoding:UTF-8>
p "日本語".inspect # => "\"\\u65E5\\u672C\\u8A9E\""
p "日本語".inspect.encoding # => #<Encoding:Windows-31J>
なので、"日本語".inspect
の時点で\u
表記への変換が行われている事
および、その理由が文字コードを変換しつつ元の情報を損なわないための措置という事がわかります。
"日本語".encoding
はるりま: 多言語化に
リテラルのエンコーディング
文字列リテラル、正規表現リテラルそしてシンボルリテラルから生成されるオブジェクトのエンコーディングは スクリプトエンコーディングになります。
現在のスクリプトエンコーディングは __ENCODING__ により取得することができます。
とある通り、スクリプトエンコーディング(__ENCODING__
)によって取得できます。
また、Ruby2.0以降のスクリプトエンコーディングの既定はUTF-8です
では、"日本語".inspect
は?というと
るびマ Ruby M17N の設計と実装
Encoding.default_internal が設定されている場合は、全ての入力された String のエンコーディングは Encoding.default_internal の返すエンコーディングと等しいと仮定することが可能になります。この場合、ライブラリが返す文字列も Encoding.default_internal になっているべきです。
ライブラリが返す文字列は、Encoding.default_internal
になっているべき という事なのでEncoding.default_internal
によって指定できる事がわかります。
結論
Encoding.default_internal = __ENCODING__
を行うことによって、String#inspect
が返す文字列を文字列リテラルと同じエンコーディングにできる。
問題点
Windowsではlocaleがcp932
なので
文字列内に絵文字などのcp932に変換できない文字を含むと文字化けします。
この問題のためにdefault_internal
がnil
の場合はdefault_external
を代替エンコーディングとして使っていると推測できます。