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
310
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
6
10年物のRailsアプリにキャッチアップ!〜コードを読まずに理解したかった〜
ima1zumi
0
20
RubyKaigiの登壇者一覧ページを作った
ima1zumi
0
200
Relineのその後の生活
ima1zumi
0
150
IRB and Reline Kaigi 2024
ima1zumi
0
7
Exploring Reline: Enhancing Command Line Usability
ima1zumi
3
13k
Reline 1分 Cooking
ima1zumi
0
21
続・mruby/cにUTF-8 を実装する
ima1zumi
1
21
UTF-8 is coming to mruby/c
ima1zumi
4
5.2k
Featured
See All Featured
RailsConf 2023
tenderlove
29
900
Why You Should Never Use an ORM
jnunemaker
PRO
54
9k
Optimizing for Happiness
mojombo
376
70k
GraphQLとの向き合い方2022年版
quramy
43
13k
Into the Great Unknown - MozCon
thekraken
32
1.5k
CSS Pre-Processors: Stylus, Less & Sass
bermonpainter
356
29k
Exploring the Power of Turbo Streams & Action Cable | RailsConf2023
kevinliebholz
27
4.2k
The Art of Programming - Codeland 2020
erikaheidi
52
13k
Teambox: Starting and Learning
jrom
133
8.8k
Cheating the UX When There Is Nothing More to Optimize - PixelPioneers
stephaniewalter
280
13k
Designing for humans not robots
tammielis
250
25k
What's in a price? How to price your products and services
michaelherold
243
12k
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