Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
RubyのStringとencodingと / ruby-string-and-encoding
Search
ima1zumi
March 24, 2021
2
340
RubyのStringとencodingと / ruby-string-and-encoding
ima1zumi
March 24, 2021
Tweet
Share
More Decks by ima1zumi
See All by ima1zumi
Exploring Reline: Enhancing Command Line Usability
ima1zumi
0
50
10年物のRailsアプリにキャッチアップ!〜コードを読まずに理解したかった〜
ima1zumi
0
62
RubyKaigiの登壇者一覧ページを作った
ima1zumi
0
260
Relineのその後の生活
ima1zumi
0
190
IRB and Reline Kaigi 2024
ima1zumi
0
7
Exploring Reline: Enhancing Command Line Usability
ima1zumi
3
14k
Reline 1分 Cooking
ima1zumi
0
25
続・mruby/cにUTF-8 を実装する
ima1zumi
1
23
UTF-8 is coming to mruby/c
ima1zumi
4
5.3k
Featured
See All Featured
StorybookのUI Testing Handbookを読んだ
zakiyama
28
5.4k
GitHub's CSS Performance
jonrohan
1030
460k
[RailsConf 2023 Opening Keynote] The Magic of Rails
eileencodes
28
9.2k
Why You Should Never Use an ORM
jnunemaker
PRO
55
9.2k
Speed Design
sergeychernyshev
25
760
Into the Great Unknown - MozCon
thekraken
34
1.6k
Visualization
eitanlees
146
15k
Designing for humans not robots
tammielis
250
25k
RailsConf 2023
tenderlove
29
980
Documentation Writing (for coders)
carmenintech
67
4.6k
Java REST API Framework Comparison - PWX 2021
mraible
28
8.4k
Rebuilding a faster, lazier Slack
samanthasiow
79
8.8k
Transcript
RubyのStringと RubyのStringと encodingと encodingと 2021-03-24 Fukuoka.rb 200回 LT大会 (#202) 1
自己紹介 自己紹介 Twitter: GitHub: Blog: FJORD BOOT CAMP 卒業生 永和システムマネジメント
好きなgemはirbとreline ima1zumi ima1zumi いまブログ 2
今日話すこと 今日話すこと MySQL 4.0 との闘い String オブジェクトは encoding とバイト列とい う情報を持ってる
encoding の扱い方 3
ある日のこと ある日のこと MySQL 4.0 🐬 にencodingがEUC-JPの 文字列をどうしても入れたくなった Rails から Sequel,
mysql2 gem 経由で入れたい ActiveRecord は MySQL 4.0 はサポート対象外 4
EUC-JPとは EUC-JPとは UNIX / Linux 系の環境ではよく使われている符号 化方式 日本語が扱える 5
MySQL 4.0 側の設定 🐬 MySQL 4.0 側の設定 🐬 my.cnf に
default-character-set = ujis を設定 他の文字コード設定値は、ほとんど MySQL 4.1 から入った機能で使用不可能だった 😭 6
とりあえずEUC-JPで入れてみる とりあえずEUC-JPで入れてみる String#encode を使おう User.new(name: '羊'.encode(Encoding::EUC_JP)).save 7
MySQLの中を 覗いてみる MySQLの中を 覗いてみる MySQLに入ってる文字のバイト列を知りたい hex(<column-name>) UTF-8のバイト列だった 8
MySQLに MySQLにUTF-8 UTF-8のバイト列が入る のバイト列が入る とても困る おそらく mysql2 gem が UTF-8
に変換している MySQL 4.0 はサポート対象外だし仕方ない … なんとかして EUC-JP で入れたい MySQL 側の設定でなんとかするのは難しそう (私が見つけられなかっただけかも) あなたならどうする? 9
私はこうした 私はこうした '羊'.encode(Encoding::EUC_JP).force_encoding(Encoding::ASCII_8BIT) 10
ここからStringの話 😊 ここからStringの話 😊 11
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
script encoding(2) script encoding(2) '羊' は encoding が UTF-8 の
String オブジェクトを生成している '羊' 13
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
注意点 注意点 クォーテーションで 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
Rubyで文字列のバイト列を調べる Rubyで文字列のバイト列を調べる String#unpack("H*") '羊'.unpack("H*") # => ["e7be8a"] 16
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
ASCII-8BITとは? ASCII-8BITとは? Stringでバイト列を扱うためのencoding ASCIIではない (ASCIIはUS-ASCII) ASCII互換 18
なぜ force_encoding したか なぜ force_encoding したか encodingがEUC-JPだとなぜかUTF-8にされた encodingを尊重してくれない … encodingをバイナリ扱い(ASCII-8BIT)にすればバ
イナリがきたと思って尊重してくれるのではない か? バイト列はEUC-JPでも MySQL 4.0氏は自分に何が入ってるか気にして なかった 19
データを取り出して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
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
まとめ まとめ RubyのStringはscript encodingでエンコードされ る。script encodingはlocale encodingに影響され ている 最近はUTF-8が多い ASCII-8BITはRubyでバイト列を扱うための
encoding。ASCII互換。 22
encode encode と と force_encoding force_encoding String#encode バイト列とencodingを変更する 第1引数に変換先(必須)、第2引数に変換元(任意) 変換できない場合例外になる
String#force_encoding encodingだけを変更する バイト列は変更しない 変換できるかどうかチェックしない 23
参考資料 参考資料 class String (Ruby リファレンスマニュアル) class Encoding (Ruby リファレンスマニュアル)
Ruby M17N の設計と実装 A Reintroduction To Ruby M17 N 改訂新版 プログラマのための文字コード技術入門 24