Crystalの文字エンコーディング

2/16 に Crystal 0.12 がリリースされました。

0.12 では Crystal に文字エンコーディング変換の仕組みが導入されました。

Ruby と同じような感じで String#encodeIO#set_encoding 等が追加されました。

といっても Crystal の文字エンコーディングは Ruby とは異なり UTF-8 固定です。そのためString#encode で変換後のデータは String ではなく Slice です。UTF-8 への変換でも同じです。

"ほげ".encode("cp932") #=> [130, 217, 130, 176]
"ほげ".encode("utf-8") #=> [227, 129, 187, 227, 129, 146]

UTF-8 以外のエンコーディングで書かれたファイルに読み書きするには、File.open にエンコーディングを指定します。

% od -tx1 hoge.txt        # hoge.txt には CP932 で「ほげ」と書かれている
0000000 82 d9 82 b0 0a
0000005
File.open("hoge.txt", encoding: "cp932").gets  #=> UTF-8 で"ほげ\n"
File.open("fuga.txt", "w", encoding: "cp932") do |f|
  f.puts "ふが"
end
% od -tx1 fuga.txt        # fuga.txt には CP932 で「ふが」と書かれる
0000000 82 d3 82 aa 0a
0000005

Ruby はエンコーディング変換を自前で行っていますが、Crystal はエンコーディングの変換に iconv を使用しているため、使用できるエンコーディングは環境に依存します。

たとえば、手元の環境(Ubuntu 15.10)の iconv には CP50221(日本でよく ISO-2022-JP と詐称してメールで使われるエンコーディング)がなかったので、メールを扱うのにはちょっと厳しい感じです。