やったもん勝ち

主にプログラミングのこと。生産性向上の某とかも。

macのrubyで文字コードcp932でファイルに保存されているか確認する際の落とし穴

まずは元々の挙動を確認

まずは何も指定もせずにファイルに保存するとどうなるのか確認してみます。

say_nice.rb

File.open("nice.txt", "w") do |f|
    f.puts "nice"
end

ファイルの文字コードを確認する方法は

$ nkf --guess filenameまたは$ file --mime filename なので、

$ nkf --guess nice.txt

で確認すると、

ASCII (LF)

どうやらASCII (LF)という文字コードで保存されているらしい。

$ file --mime nice.txt

こちらでも確認してみます。

good.txt: text/plain; charset=us-ascii

ふむ。やはりASCIIみたいですね。

それでは、文字コードをcp932に変更します。 ちなみにcp932というのはShift-JISみたいなやつです。若干違うけどほぼ一緒みたいな認識を勝手にしてます。

say_nice.rb

File.open("nice.txt", "w:cp932") do |f|
    f.puts "nice"
end

これで文字コードはcp932になっているはずですね、確認してみましょう。

$ nkf --guess nice.txt

ASCII (LF)

ファッ!? 変わってないやんけ!

念のためこちらでも確認。

$ file --mime nice.txt

good.txt: text/plain; charset=us-ascii

おっかしいなー。

思い通りの文字コードで保存されない理由

思い通りの文字コードで保存されない理由は、アルファベットしかないから。です。

上記のコードたちだとアルファベットしか出力してないから、文字コードを判断するに足る情報が少なかったからです。

文字コードというのはhtmlファイルのhead情報みたいにファイルのどこかに保存されているのかなと、勝手に思ってましたが、ファイルの中身を見て判断しているみたいですね。

テキストファイルの文字コードは中身で決まる。らしい。 - Qiita

こちら参考にさせていただきました。

つまり、niceだけだと、asciiもutf-8もcp932も同じ文字コードで表現できてしまう。ってこと!か

というわけで、再度確認してみる

再度元々の挙動を確認

日本語文字に変更して、

say_nice.rb

File.open("nice.txt", "w") do |f|
    f.puts "いいね"
end

$ nkf --guess nice.txt

UTF-8 (LF)

$ file --mime nice.txt

good.txt: text/plain; charset=utf-8

日本語文字を含めると、UTF-8で保存されているみたいですね。

いよいよ本題、cp932で保存したい。

File.open("nice.txt", "w:cp932") do |f|
    f.puts "いいね"
end

確認してみる。

$ nkf --guess nice.txt

Shift_JIS (LF)

えぇ〜・・・

こちらも

$ file --mime nice.txt

good.txt: text/plain; charset=unknown-8bit

こっちに至ってはunknown言われてるやん。。。

cp932じゃなく、Shift_JISと解釈される問題

$ file --mime nice.txtの方はさておき、Shift_JIS (LF)と判別されるのは、同じく、cp932Shift_JIS (LF)を判別する文字がなかったためでした。

cp932にあって、Shift_JISにないものを文字に入れて検証。 を追加。

File.open("nice.txt", "w:cp932") do |f|
    f.puts "いいね①"
end

これで

$ nkf --guess nice.txt

CP932 (LF)

よっしゃ!

こちらは?

$ file --mime nice.txt

good.txt: text/plain; charset=unknown-8bit

unknownのまま。 もうfile --mimeのことなんか知らないっ あとで調べてみるか・・・

cp932で保存はできてるんだもんな。