YAML.dumpするときは、文字コードを意識しとくべきだった件
なんかハマったので。環境はRuby1.9.3です。
YAML.dumpで出力しようとしたときに、必ずしも人間にわかりやすい形で出力してくれるとは限らないんですな。
とりあえず、ファイルに出力してみる場合。
>>> content = 'hello, world!!' >>> hash_test = {'key' => Digest::MD5.hexdigest(content)} >>> open('./test.out',"w") do |fh| >>> fh.write hash_test >>> end >>> >>> puts File.open("./test.out").read 9fe4fa1a9c66b49ffef769c595bfd9ec
んで、test.outにはこんな感じでデータが入ってる。
$ cat test.out {"key"=>"9fe4fa1a9c66b49ffef769c595bfd9ec"}%
単にハッシュがそのまま出力されてるだけですな。
次に、yaml。 ハッシュなので、jsonとかyamlとかだとシンプルに出力できるので、やってみた。
>>> content = 'hello, world!!' >>> content_hash = {'key1' => Digest::MD5.hexdigest(content)} >>> open('./test.yaml',"w") do |fh| >>> YAML.dump(content_hash, fh) >>> end >>> puts YAML.load_file('./test.yaml') {"key1"=>"9fe4fa1a9c66b49ffef769c595bfd9ec"}
ここまでは普通っすな。 んで、ファイルを見てみる。
$ cat hash.yaml --- key1: !binary |- OWZlNGZhMWE5YzY2YjQ5ZmZlZjc2OWM1OTViZmQ5ZWM=
こんな感じで出力されてるわけですな。「!binary」ってなんぞと。どうもググってみると、文字コードが原因みたい。 ファイルの文字コード指定してないとこんな感じ。
>>> content = 'hello, world!!' >>> filehash = Digest::MD5.hexdigest(content) >>> puts content.encoding >>> puts filehash.encoding US-ASCII ASCII-8BIT
んで、magic comment使って、文字コード指定してみた。
>>> # -*- coding: utf-8 -*- >>> content = 'hello, world!!' >>> filehash = Digest::MD5.hexdigest(content) >>> puts content.encoding >>> puts filehash.encoding UTF-8 ASCII-8BIT
MD5でハッシュとったものは相変わらずASCII-8BITなんすな。hexdigestで出力されるのはこのバイナリエンコーディング?っぽいわけです。
なんで、とりあえず読みやすくするため、安直にUTF-8に変換して、yaml.dumpしてみる(バイナリのユニコード化が正しいかは分からない…)。
>>> content = 'hello, world!!' >>> content_hash = {'key1' => Digest::MD5.hexdigest(content).encode("UTF-8")} >>> open('./test.yaml',"w") do |fh| >>> YAML.dump(content_hash, fh) >>> end >>> puts YAML.load_file('./test.yaml') {"key1"=>"9fe4fa1a9c66b49ffef769c595bfd9ec"}
んで、ファイルのほうも見やすくなりました。
$ cat test.yaml --- key1: 9fe4fa1a9c66b49ffef769c595bfd9ec
ということで、md5にハッシュ化したものはUTF-8に変換しておいたほうが読みやすくていいかもねという話でした。
ぐぐってたら、こういうサイトとかに、Psychとかのエンジンの話が書かれていたので、そういう問題が絡んでるのかなと思いつつ、1.9.3なので関係なさそうです。
いずれにしても、YAML.dumpのときの文字コードは気をつけておくほうがベター。エンジンとかまで調べきれてなくてすいません…