Upgrade to Pro — share decks privately, control downloads, hide ads and more …

RubyのStringとencodingと / ruby-string-and-encoding

74b5a82b8710accc1e6189a19f0b4935?s=47 ima1zumi
March 24, 2021
110

RubyのStringとencodingと / ruby-string-and-encoding

74b5a82b8710accc1e6189a19f0b4935?s=128

ima1zumi

March 24, 2021
Tweet

Transcript

  1. RubyのStringと RubyのStringと encodingと encodingと 2021-03-24 Fukuoka.rb 200回 LT大会 (#202) 1

  2. 自己紹介 自己紹介 Twitter: GitHub: Blog: FJORD BOOT CAMP 卒業生 永和システムマネジメント

    好きなgemはirbとreline ima1zumi ima1zumi いまブログ 2
  3. 今日話すこと 今日話すこと MySQL 4.0 との闘い String オブジェクトは encoding とバイト列とい う情報を持ってる

    encoding の扱い方 3
  4. ある日のこと ある日のこと MySQL 4.0 🐬 にencodingがEUC-JPの 文字列をどうしても入れたくなった Rails から Sequel,

    mysql2 gem 経由で入れたい ActiveRecord は MySQL 4.0 はサポート対象外 4
  5. EUC-JPとは EUC-JPとは UNIX / Linux 系の環境ではよく使われている符号 化方式 日本語が扱える 5

  6. MySQL 4.0 側の設定 🐬 MySQL 4.0 側の設定 🐬 my.cnf に

    default-character-set = ujis を設定 他の文字コード設定値は、ほとんど MySQL 4.1 から入った機能で使用不可能だった 😭 6
  7. とりあえずEUC-JPで入れてみる とりあえずEUC-JPで入れてみる String#encode を使おう User.new(name: '羊'.encode(Encoding::EUC_JP)).save 7

  8. MySQLの中を 覗いてみる MySQLの中を 覗いてみる MySQLに入ってる文字のバイト列を知りたい hex(<column-name>) UTF-8のバイト列だった 8

  9. MySQLに MySQLにUTF-8 UTF-8のバイト列が入る のバイト列が入る とても困る おそらく mysql2 gem が UTF-8

    に変換している MySQL 4.0 はサポート対象外だし仕方ない … なんとかして EUC-JP で入れたい MySQL 側の設定でなんとかするのは難しそう (私が見つけられなかっただけかも) あなたならどうする? 9
  10. 私はこうした 私はこうした '羊'.encode(Encoding::EUC_JP).force_encoding(Encoding::ASCII_8BIT) 10

  11. ここからStringの話 😊 ここからStringの話 😊 11

  12. script encoding(1) script encoding(1) encoding が UTF-8 の String オブジェクトを作成

    " ' で String を生成するときの encoding は script encoding に依存 String.new では encoding を指定できる script encoding は環境依存 $LC_ALL, $LC_CTYPE, $LANG 等で決まってそう 多分このへん '羊' ruby/langinfo.c#L69-L71 12
  13. script encoding(2) script encoding(2) '羊' は encoding が UTF-8 の

    String オブジェクトを生成している '羊' 13
  14. String#encode String#encode String#encode 第1引数に変換先のencoding(必須) 第2引数に変換元のencoding(任意) option: 不正バイト, 文字がない場合, 置換文字 encodingは文字列でもEncodingクラスの定数でも

    OK encode("UTF-8") 🙆 encode(Encoding::UTF_8) 🙆 '羊'.encode(Encoding::EUC_JP) 14
  15. 注意点 注意点 クォーテーションで String を生成すると 変数展開した中で encode しても script encoding

    で エンコードされる String.new に encoding を渡すか 生成後に encode する mee = '羊' p '#{mee.encode(Encoding::EUC_JP)}'.encoding # => #<Encoding:UTF-8> String.new('羊', encoding: Encoding::EUC_JP) mee = '羊' '#{mee.encode(Encoding::EUC_JP)}'.encode(Encoding::EUC_JP) 15
  16. Rubyで文字列のバイト列を調べる Rubyで文字列のバイト列を調べる String#unpack("H*") '羊'.unpack("H*") # => ["e7be8a"] 16

  17. force_encoding force_encoding encoding情報のみを変更する バイト列は変更しない バイト列がEUC-JP, encodingがASCII-8BITの String '羊'.encode(Encoding::EUC_JP).force_encoding(Encoding::ASCII_8BIT) mee =

    '羊'.encode(Encoding::EUC_JP).force_encoding(Encoding::ASCII_8BIT) => "\xCD\xD3" mee.encoding => #<Encoding:ASCII-8BIT> mee.unpack("H*") => ["cdd3"] 17
  18. ASCII-8BITとは? ASCII-8BITとは? Stringでバイト列を扱うためのencoding ASCIIではない (ASCIIはUS-ASCII) ASCII互換 18

  19. なぜ force_encoding したか なぜ force_encoding したか encodingがEUC-JPだとなぜかUTF-8にされた encodingを尊重してくれない … encodingをバイナリ扱い(ASCII-8BIT)にすればバ

    イナリがきたと思って尊重してくれるのではない か? バイト列はEUC-JPでも MySQL 4.0氏は自分に何が入ってるか気にして なかった 19
  20. データを取り出してUTF-8にする データを取り出してUTF-8にする MySQL 4.0 からデータ取得するとencodingは ASCII-8BITになっていた 誰もencodingを教えてくれていない … バイト列はEUC-JP EUC-JPからUTF-8にしたい

    mee = User.where(id: 1).first #sequel mee.encoding # => #<Encoding:ASCII-8BIT> 20
  21. encodingがASCII-8BITで encodingがASCII-8BITで バイト列がEUC-JPのString バイト列がEUC-JPのString そのままencodeはできない 自分がASCII-8BITだと思っているので Stringに自分が何者か教える mee.unpack("H*") => ["cdd3"]

    mee.encoding => ASCII-8BIT mee.encode(Encoding::UTF_8) `encode': "\xCD" from ASCII-8BIT to UTF-8 (Encoding::UndefinedConversionError) '羊'.encode(Encoding::UTF_8, Encoding::EUC_JP) 21
  22. まとめ まとめ RubyのStringはscript encodingでエンコードされ る。script encodingはlocale encodingに影響され ている 最近はUTF-8が多い ASCII-8BITはRubyでバイト列を扱うための

    encoding。ASCII互換。 22
  23. encode encode と と force_encoding force_encoding String#encode バイト列とencodingを変更する 第1引数に変換先(必須)、第2引数に変換元(任意) 変換できない場合例外になる

    String#force_encoding encodingだけを変更する バイト列は変更しない 変換できるかどうかチェックしない 23
  24. 参考資料 参考資料 class String (Ruby リファレンスマニュアル) class Encoding (Ruby リファレンスマニュアル)

    Ruby M17N の設計と実装 A Reintroduction To Ruby M17 N 改訂新版 プログラマのための文字コード技術入門 24