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
330
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
34
10年物のRailsアプリにキャッチアップ!〜コードを読まずに理解したかった〜
ima1zumi
0
60
RubyKaigiの登壇者一覧ページを作った
ima1zumi
0
230
Relineのその後の生活
ima1zumi
0
180
IRB and Reline Kaigi 2024
ima1zumi
0
7
Exploring Reline: Enhancing Command Line Usability
ima1zumi
3
13k
Reline 1分 Cooking
ima1zumi
0
22
続・mruby/cにUTF-8 を実装する
ima1zumi
1
22
UTF-8 is coming to mruby/c
ima1zumi
4
5.2k
Featured
See All Featured
Become a Pro
speakerdeck
PRO
26
5k
How STYLIGHT went responsive
nonsquared
96
5.2k
Gamification - CAS2011
davidbonilla
80
5.1k
What’s in a name? Adding method to the madness
productmarketing
PRO
22
3.2k
The Art of Programming - Codeland 2020
erikaheidi
53
13k
Building Adaptive Systems
keathley
38
2.3k
Rails Girls Zürich Keynote
gr2m
94
13k
The Psychology of Web Performance [Beyond Tellerrand 2023]
tammyeverts
45
2.2k
Distributed Sagas: A Protocol for Coordinating Microservices
caitiem20
330
21k
Site-Speed That Sticks
csswizardry
2
190
Bootstrapping a Software Product
garrettdimon
PRO
305
110k
Design and Strategy: How to Deal with People Who Don’t "Get" Design
morganepeng
127
18k
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