読者です 読者をやめる 読者になる 読者になる

Rails Webook

自社のECを開発している会社で働いています。Rails情報やサービスを成長させる方法を書いていきます

Ruby/Railsで文字コードの変換(エンコード)とエンコーディングの確認方法のまとめ

Ruby/Railsで文字コードの変換(エンコード)とエンコーディングの確認方法をまとめました。
Ruby標準で、下記のような文字コードを変換、確認するライブラリがあるのですが、どれを使ったらわからないのでまとめてみました。
ちなみに、Ruby 2.0からはutf-8がデフォルトのコードです。

Rubyで文字コードの変換

  • String型のencodeメソッド => Encoding::UndefinedConversationErrorrが発生する、オプションで防げる
  • KConvのto*やkconvメソッド => 基本的には問題無いが、半角が全角になる(MIMEがデコードされる?)
  • NKFのnkfメソッド => 基本的には問題無い。半角も半角のままできる(MIMEも)。KConvは内部的にNKFを使っている。
  • Iconv (未調査)
  • Uconv (未調査) => Ruby標準ではないっぽい

Rubyで文字コードの確認

  • String型のencodingメソッド
  • KConvのguessメソッド
  • NKFのguessメソッド

文字コードの変換と確認比較(UTF-8 => SJIS)

# ###############
# 変換前の文字列
# ###############
str = "全角 ハンカク 〜−¢£¬−‖"

# ###############
# 変換後の文字列
# ###############
# endodeメソッドでCP932(Windows用のSJIS拡張)に変換
str.encode("CP932") 
# => エラーが発生 Encoding::UndefinedConversionError: U+301C from UTF-8 to Windows-31J

# endodeメソッドでCP932(※1)に変換
# エラーは発生しなくなるが、? で置き換えられる
str.encode("cp932", :invalid => :replace, :undef => :replace)
# => "全角 ハンカク ???????"
# encoding "Windows-31J" / Kconv.guess "Shift_JIS" / NKF.guess "Shift_JIS"

# endodeメソッドでCP932に変換(※2 sjis_safeメソッドは下記参照)
sjis_safe(str).encode("cp932", :invalid => :replace, :undef => :replace)
# => "全角 ハンカク 〜−¢£¬−‖"
# encoding "Windows-31J" / Kconv.guess "Shift_JIS" / NKF.guess "Shift_JIS"

# KconvでSJISに変換(半角が全角に変換される、MIMEデコードされるぽい)
require 'kconv'
str.kconv(Kconv::SJIS)
# => "全角 ハンカク 〜−¢£¬−‖"
# encoding "Shift_JIS" / Kconv.guess "Shift_JIS" / NKF.guess "Shift_JIS"

# NKFでSJISに変換(-xm0: 半角、MIMEデコードをしない)
NKF.nkf("-xm0 -s", str)
# => "全角 ハンカク 〜−¢£¬−‖"
# encoding "Shift_JIS" / Kconv.guess "Shift_JIS" / NKF.guess "Shift_JIS"

文字コードの変換と確認比較(SJIS => UTF-8)

変換方法の差異がある可能生があるので、できるだけ同じメソッドを使うようにしてください。
下記は、同じメソッドで確認しています。

sjis_str = "全角 ハンカク 〜−¢£¬−‖" # エンコーディングはSJIS

# endodeメソッドでUTF-8に変換
sjis_str.encode("cp932", :invalid => :replace, :undef => :replace)
# => "全角 ハンカク 〜−¢£¬−‖"

# KconvでUTF-8に変換(半角が全角に変換される、MIMEデコードされるぽい)
require 'kconv'
sjis_str.kconv(Kconv::UTF8)
# => "全角 ハンカク 〜−¢£¬−‖"

# NKFでUTF-8に変換(-xm0: 半角、MIMEデコードをしない)
NKF.nkf("-xm0 -w", sjis_str)
# => "全角 ハンカク 〜−¢£¬−‖"
※1 CP932 とは

Windows用のSJIS拡張であり、"Windows31-J"と同様

※2 sjis_safeメソッドの実装
def sjis_safe(str)
[
  ["301C", "FF5E"], # wave-dash
  ["2212", "FF0D"], # full-width minus
  ["00A2", "FFE0"], # cent as currency
  ["00A3", "FFE1"], # lb(pound) as currency
  ["00AC", "FFE2"], # not in boolean algebra
  ["2014", "2015"], # hyphen
  ["2016", "2225"], # double vertical lines
].inject(str) do |s, (before, after)|
  s.gsub(
    before.to_i(16).chr('UTF-8'),
    after.to_i(16).chr('UTF-8'))
  end
end