カイワレの大冒険 Third

技術的なことや他愛もないことをたまに書いてます

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のときの文字コードは気をつけておくほうがベター。エンジンとかまで調べきれてなくてすいません…