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
32
10年物のRailsアプリにキャッチアップ!〜コードを読まずに理解したかった〜
ima1zumi
0
55
RubyKaigiの登壇者一覧ページを作った
ima1zumi
0
220
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
GitHub's CSS Performance
jonrohan
1030
460k
We Have a Design System, Now What?
morganepeng
51
7.3k
Practical Orchestrator
shlominoach
186
10k
Raft: Consensus for Rubyists
vanstee
137
6.7k
What’s in a name? Adding method to the madness
productmarketing
PRO
22
3.2k
The Invisible Side of Design
smashingmag
298
50k
Designing Experiences People Love
moore
138
23k
Documentation Writing (for coders)
carmenintech
66
4.5k
The Web Performance Landscape in 2024 [PerfNow 2024]
tammyeverts
2
290
Agile that works and the tools we love
rasmusluckow
328
21k
Templates, Plugins, & Blocks: Oh My! Creating the theme that thinks of everything
marktimemedia
28
2.1k
A Tale of Four Properties
chriscoyier
157
23k
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