Rubyのエンコーディング                             NSEG#30                          とみたまさひろ                             2012-08-25R...
自己紹介      ✓ とみた まさひろ (ペンネーム)      ✓ プログラマー (Ruby & C)      ✓ http://d.hatena.ne.jp/tmtms      ✓ http://twitter.com/tmtms  ...
NSEG      ✓ #1 Rubyの黒魔術      ✓ #3 はじめてのRuby拡張ライブラリ      ✓ #6 Ruby紹介      ✓ #11 RSpecとCucumber      ✓ #13 システムコール      ✓ #1...
Ruby 1.8        は      オワコンRubyのエンコーディング - NSEG#30                                        3/45                          Po...
1.8.7の今後につきまして                   ✓ 2012年6月まで、通常のメン                     テナンスが続きます。                   ✓ それ以降、バグフィックスリリー     ...
Ruby 1.9   を使いまし     ょうRubyのエンコーディング - NSEG#30                                        5/45                          Powere...
1.9の          特徴Rubyのエンコーディング - NSEG#30                                        6/45                          Powered by Ra...
一番大きい  のはエンコ  ーディングRubyのエンコーディング - NSEG#30                                        7/45                          Powered by...
Rubyのエンコーディング      http://d.hatena.ne.jp/tmtms/20120812/ruby_encoding                                                     ...
エンコーディング?      ✓ 文字符号化方式      ✓ UTF-8 とか EUC-JP とか SHIFT_JIS とか        そーゆー奴      ✓ charset とか呼ばれたり      ✓ いわゆる「文字コード」    ...
同じ文字でも異なるコード      「あ」      ✓ UTF-8 では 0xE3 0x81 0x82 の3バイト      ✓ EUC-JP では 0xA4 0xA2 の2バイト      ✓ SHIFT_JIS では 0x82 0xA0 ...
同じバイト列でも別の文字      0xC2 0xA9 の2バイトは      ✓ UTF-8 では「©」1文字      ✓ EUC-JP では「息」1文字      ✓ SHIFT_JIS では「ツゥ」2文字                ...
Ruby 1.8.x      ✓ "xC2xA9" という文字列は Ruby 的にはた        だのバイト列      ✓ エンコーディング情報を持たない      ✓ "©"(UTF-8) として扱うか "息"(EUC-JP) とし ...
Ruby 1.9.x      ✓ 文字列のエンコーディングは文字列自身が知        っている      ✓ "©"(UTF-8) と "息"(EUC-JP) は同じバイト列        だけど異なる文字列      ✓ "あ"(UTF...
ちゃんと文字として扱える                # Ruby 1.8.7                "文字".size       #=>   6                "文字".bytesize   #=>   6    ...
String#encoding    文字列のエンコーディングを調べる           "あ".encoding #=> #<Encoding:UTF-8>                                          ...
String#encode    エンコーディング変換             str = "あ"             str.encoding   #=> #<Encoding:UTF-8>             str2 = str....
エンコーディングは何で決まる?      ✓ スクリプトエンコーディング      ✓ 外部エンコーディング      ✓ 内部エンコーディング                                      17/45Rubyのエン...
スクリプトエンコーディング      ✓ スクリプト中の文字列リテラルのエンコーディ        ングを決定する      ✓ スクリプト先頭行のマジックコメントで指定する              # coding: utf-8      ...
スクリプトエンコーディング      ✓ US-ASCII で範囲外の "xHH" 表記を含む場        合は ASCII-8BIT      ✓ "uXXXX" 表記を含む場合は UTF-8              # coding:...
外部エンコーディング      ✓ ファイル内の文字列が何のエンコーディングか        を指定する      ✓ File.open 時に指定する              f = File.open("file.txt", "r:utf...
外部エンコーディング(書き込み)           f = File.open("file.txt", "w:utf-8")           f.puts("ほげ")    ✓ 文字列が UTF-8 に変換されて書き込まれる       ...
内部エンコーディング      ✓ ファイルから読み込んだ文字列のエンコーディ        ングを変換する      ✓ File.open 時に指定する            File.open("file.txt", "r:cp932:u...
もうちょっ と詳しく                                 23/45Rubyのエンコーディング - NSEG#30   Powered by Rabbit 1.0.9
読み込み時の変換      ✓ メソッドによって変換したりしなかったり      ✓ バイナリ読み込みメソッド(常に ASCII-8BIT)           ✓ read(n) / read_nonblock / readpartial /...
外部エンコーディング未指定時    読み込み時は Encoding.default_external が使わ    れる          Encoding.default_external #=> #<Encoding:UTF-8>     ...
Encoding.default_external      ✓ -E オプション / ロケール              % ruby -Eutf-8 -e p Encoding.default_external              #...
書き込み時の変換      ✓ メソッドには依らない      ✓ IO に外部エンコーディングが指定されていた        場合は変換される      ✓ 外部エンコーディングが ASCII-8BIT の場合        は変換されない ...
正規表現  のエンコー   ディングRubyのエンコーディング - NSEG#30                                      28/45                          Powered by R...
正規表現リテラル      ✓ ASCII文字のみの場合は US-ASCII      ✓ 非ASCII文字はスクリプトエンコーディング                  # coding: utf-8                  /あ/...
正規表現リテラル      ✓ US-ASCII で範囲外の "xHH" 表記を含む場        合は ASCII-8BIT      ✓ "uXXXX" 表記を含む場合は UTF-8              # coding: us-a...
はまり         どころRubyのエンコーディング - NSEG#30                                      31/45                          Powered by Rabb...
文字列比較    文字が等しくてもエンコーディングが異なれば異なる                          u = "あ".encode("utf-8")                          s = "あ".encode...
文字列比較    バイト列が等しくてもエンコーディングが異なれば異    なる          #   coding: utf-8          u   = "あ"          b   = "あ".force_encoding("a...
文字列比較    エンコーディングが異なっていてもASCII互換のエン    コーディングでASCII文字だけなら比較できる                      #   coding: utf-8                     ...
正規表現    エンコーディングが異なっていたらエラー          # coding: utf-8          "あ" =~ /./s          # incompatible encoding regexp match (W...
正規表現    ASCII文字だけならエラーにならない                          # coding: utf-8                          "ABC" =~ /./s    ASCII文字だけでテ...
文字列結合    異なるエンコーディング同士の結合はエラー          u   = "あ".encode("utf-8")          s   = "あ".encode("cp932")          u   + s      ...
文字列結合    ASCII文字だけならエラーにならない                   u = "ABC".encode("utf-8")                   s = "DEF".encode("cp932")      ...
リテラル    スクリプトエンコーディングに合わない文字があると    スクリプトのロード時にエラー         # coding: cp932         "あ"     # UTF-8の「あ」         # invalid m...
リテラル    でも "xHH" 表記だとエラーにならない              # coding: cp932              "xE3x81x82"    # UTF-8の「あ」                        ...
不正な文字    正規表現との比較でエラー          # coding: cp932          str = "xE3x81x82" # ここではエラーにならない          str =~ /./            # ...
不正な文字    エンコーディングがあってたとしても不正な文字は発    生しうる         # 不正な文字が入っているファイルをUTF-8指定で読んでしまった         File.open("utf-8.txt", "r:utf-...
変換    内部エンコーディングを指定すると不正な文字で変    換エラー          # CP932だけど不正な文字が入ってる          f = File.open("cp932.txt", "r:cp932:utf-8")  ...
変換      ✓ 外部エンコーディングを指定してないと環境変        数の影響うけるかも      ✓ 内部エンコーディング指定すると自動的に変        換されるけど、読むだけでエラーになるかも                  ...
まとめ      ✓ 文字単位の処理は便利      ✓ ハマる時はハマる      ✓ データのエンコーディングを統一するのが吉                                            45/45Rubyのエンコ...
Upcoming SlideShare
Loading in …5
×

Rubyのエンコーディング

17,926 views

Published on

Published in: Technology
0 Comments
17 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
17,926
On SlideShare
0
From Embeds
0
Number of Embeds
8,076
Actions
Shares
0
Downloads
22
Comments
0
Likes
17
Embeds 0
No embeds

No notes for slide

Rubyのエンコーディング

  1. 1. Rubyのエンコーディング NSEG#30 とみたまさひろ 2012-08-25Rubyのエンコーディング - NSEG#30 Powered by Rabbit 1.0.9
  2. 2. 自己紹介 ✓ とみた まさひろ (ペンネーム) ✓ プログラマー (Ruby & C) ✓ http://d.hatena.ne.jp/tmtms ✓ http://twitter.com/tmtms ✓ 好きなもの ✓ Ruby, MySQL, Ubuntu, Emacs, Git 1/45Rubyのエンコーディング - NSEG#30 Powered by Rabbit 1.0.9
  3. 3. NSEG ✓ #1 Rubyの黒魔術 ✓ #3 はじめてのRuby拡張ライブラリ ✓ #6 Ruby紹介 ✓ #11 RSpecとCucumber ✓ #13 システムコール ✓ #14 MySQLの文字コード ✓ #18 Rabbit ✓ #20 TDDについて ✓ #21 LinuxのメモリRubyのエンコーディング - NSEG#30 2/45 Powered by Rabbit 1.0.9
  4. 4. Ruby 1.8 は オワコンRubyのエンコーディング - NSEG#30 3/45 Powered by Rabbit 1.0.9
  5. 5. 1.8.7の今後につきまして ✓ 2012年6月まで、通常のメン テナンスが続きます。 ✓ それ以降、バグフィックスリリー スは終了いたします。2013年 6月まではセキュリティフィック スは続けますので、それまでは 1.8.7をお使いいただけます。 ✓ 2013年6月より先は、1.8.7 はあらゆるサポート対象外に なります。 http://www.ruby-lang.org/ja/news/2011/10/07/plans-for-1-8-7/ 4/45Rubyのエンコーディング - NSEG#30 Powered by Rabbit 1.0.9
  6. 6. Ruby 1.9 を使いまし ょうRubyのエンコーディング - NSEG#30 5/45 Powered by Rabbit 1.0.9
  7. 7. 1.9の 特徴Rubyのエンコーディング - NSEG#30 6/45 Powered by Rabbit 1.0.9
  8. 8. 一番大きい のはエンコ ーディングRubyのエンコーディング - NSEG#30 7/45 Powered by Rabbit 1.0.9
  9. 9. Rubyのエンコーディング http://d.hatena.ne.jp/tmtms/20120812/ruby_encoding 8/45Rubyのエンコーディング - NSEG#30 Powered by Rabbit 1.0.9
  10. 10. エンコーディング? ✓ 文字符号化方式 ✓ UTF-8 とか EUC-JP とか SHIFT_JIS とか そーゆー奴 ✓ charset とか呼ばれたり ✓ いわゆる「文字コード」 9/45Rubyのエンコーディング - NSEG#30 Powered by Rabbit 1.0.9
  11. 11. 同じ文字でも異なるコード 「あ」 ✓ UTF-8 では 0xE3 0x81 0x82 の3バイト ✓ EUC-JP では 0xA4 0xA2 の2バイト ✓ SHIFT_JIS では 0x82 0xA0 の2バイト 10/45Rubyのエンコーディング - NSEG#30 Powered by Rabbit 1.0.9
  12. 12. 同じバイト列でも別の文字 0xC2 0xA9 の2バイトは ✓ UTF-8 では「©」1文字 ✓ EUC-JP では「息」1文字 ✓ SHIFT_JIS では「ツゥ」2文字 11/45Rubyのエンコーディング - NSEG#30 Powered by Rabbit 1.0.9
  13. 13. Ruby 1.8.x ✓ "xC2xA9" という文字列は Ruby 的にはた だのバイト列 ✓ エンコーディング情報を持たない ✓ "©"(UTF-8) として扱うか "息"(EUC-JP) とし て扱うかはプログラム次第 12/45Rubyのエンコーディング - NSEG#30 Powered by Rabbit 1.0.9
  14. 14. Ruby 1.9.x ✓ 文字列のエンコーディングは文字列自身が知 っている ✓ "©"(UTF-8) と "息"(EUC-JP) は同じバイト列 だけど異なる文字列 ✓ "あ"(UTF-8) と "あ"(EUC-JP) は同じ文字を表 してるけど等しくない ✓ 同じプログラム中で複数のエンコーディングの 文字列を同時に扱える(珍しいかも) 13/45Rubyのエンコーディング - NSEG#30 Powered by Rabbit 1.0.9
  15. 15. ちゃんと文字として扱える # Ruby 1.8.7 "文字".size #=> 6 "文字".bytesize #=> 6 "文字"[0] #=> 230 (0xE6) "文字".reverse #=> "??????" # Ruby 1.9.3 "文字".size #=> 2 "文字".bytesize #=> 6 "文字"[0] #=> "文" "文字".reverse #=> "字文" 14/45Rubyのエンコーディング - NSEG#30 Powered by Rabbit 1.0.9
  16. 16. String#encoding 文字列のエンコーディングを調べる "あ".encoding #=> #<Encoding:UTF-8> 15/45Rubyのエンコーディング - NSEG#30 Powered by Rabbit 1.0.9
  17. 17. String#encode エンコーディング変換 str = "あ" str.encoding #=> #<Encoding:UTF-8> str2 = str.encode("cp932") str2.encoding #=> #<Encoding:Windows-31J> 16/45Rubyのエンコーディング - NSEG#30 Powered by Rabbit 1.0.9
  18. 18. エンコーディングは何で決まる? ✓ スクリプトエンコーディング ✓ 外部エンコーディング ✓ 内部エンコーディング 17/45Rubyのエンコーディング - NSEG#30 Powered by Rabbit 1.0.9
  19. 19. スクリプトエンコーディング ✓ スクリプト中の文字列リテラルのエンコーディ ングを決定する ✓ スクリプト先頭行のマジックコメントで指定する # coding: utf-8 "あ".encoding #=> #<Encoding:UTF-8> ✓ デフォルトは US-ASCII (または -K で指定) 18/45Rubyのエンコーディング - NSEG#30 Powered by Rabbit 1.0.9
  20. 20. スクリプトエンコーディング ✓ US-ASCII で範囲外の "xHH" 表記を含む場 合は ASCII-8BIT ✓ "uXXXX" 表記を含む場合は UTF-8 # coding: us-ascii "a".encoding #=> #<Encoding:US-ASCII> "x41".encoding #=> #<Encoding:US-ASCII> "xFF".encoding #=> #<Encoding:ASCII-8BIT> "u3042".encoding #=> #<Encoding:UTF-8> 19/45Rubyのエンコーディング - NSEG#30 Powered by Rabbit 1.0.9
  21. 21. 外部エンコーディング ✓ ファイル内の文字列が何のエンコーディングか を指定する ✓ File.open 時に指定する f = File.open("file.txt", "r:utf-8") f.gets # UTF-8文字列 ✓ ファイルの内容は UTF-8 ✓ 読み込んだ文字列も UTF-8 エンコーディング 20/45Rubyのエンコーディング - NSEG#30 Powered by Rabbit 1.0.9
  22. 22. 外部エンコーディング(書き込み) f = File.open("file.txt", "w:utf-8") f.puts("ほげ") ✓ 文字列が UTF-8 に変換されて書き込まれる 21/45Rubyのエンコーディング - NSEG#30 Powered by Rabbit 1.0.9
  23. 23. 内部エンコーディング ✓ ファイルから読み込んだ文字列のエンコーディ ングを変換する ✓ File.open 時に指定する File.open("file.txt", "r:cp932:utf-8") ✓ ファイルの内容は CP932 ✓ 読み込んだ文字列は UTF-8 エンコーディング ✓ 書き込み時はあまり関係ない 22/45Rubyのエンコーディング - NSEG#30 Powered by Rabbit 1.0.9
  24. 24. もうちょっ と詳しく 23/45Rubyのエンコーディング - NSEG#30 Powered by Rabbit 1.0.9
  25. 25. 読み込み時の変換 ✓ メソッドによって変換したりしなかったり ✓ バイナリ読み込みメソッド(常に ASCII-8BIT) ✓ read(n) / read_nonblock / readpartial / sysread ✓ テキスト読み込みメソッド ✓ foreach / readlines / each_line / lines / gets / getc / ungetc / read / readchar / readline / readlines 24/45Rubyのエンコーディング - NSEG#30 Powered by Rabbit 1.0.9
  26. 26. 外部エンコーディング未指定時 読み込み時は Encoding.default_external が使わ れる Encoding.default_external #=> #<Encoding:UTF-8> File.open("file.txt", "r:cp932").gets.encoding #=> #<Encoding:Windows-31J> File.open("file.txt", "r").gets.encoding #=> #<Encoding:UTF-8> 25/45Rubyのエンコーディング - NSEG#30 Powered by Rabbit 1.0.9
  27. 27. Encoding.default_external ✓ -E オプション / ロケール % ruby -Eutf-8 -e p Encoding.default_external #<Encoding:UTF-8> % LC_ALL=C ruby -e p Encoding.default_external #<Encoding:US-ASCII> % LC_ALL=ja_JP.UTF-8 ruby -e p Encoding.default_external #<Encoding:UTF-8> ✓ かならず値がある ✓ 外部エンコーディングのデフォルトじゃない 26/45Rubyのエンコーディング - NSEG#30 Powered by Rabbit 1.0.9
  28. 28. 書き込み時の変換 ✓ メソッドには依らない ✓ IO に外部エンコーディングが指定されていた 場合は変換される ✓ 外部エンコーディングが ASCII-8BIT の場合 は変換されない ✓ 外部エンコーディングが指定されていない場 合は変換されない(基本的には) 27/45Rubyのエンコーディング - NSEG#30 Powered by Rabbit 1.0.9
  29. 29. 正規表現 のエンコー ディングRubyのエンコーディング - NSEG#30 28/45 Powered by Rabbit 1.0.9
  30. 30. 正規表現リテラル ✓ ASCII文字のみの場合は US-ASCII ✓ 非ASCII文字はスクリプトエンコーディング # coding: utf-8 /あ/.encoding #=> #<Encoding:UTF-8> /./.encoding #=> #<Encoding:US-ASCII> /./n.encoding #=> #<Encoding:US-ASCII> /./s.encoding #=> #<Encoding:Windows-31J> /./e.encoding #=> #<Encoding:EUC-JP> /./u.encoding #=> #<Encoding:UTF-8> 29/45Rubyのエンコーディング - NSEG#30 Powered by Rabbit 1.0.9
  31. 31. 正規表現リテラル ✓ US-ASCII で範囲外の "xHH" 表記を含む場 合は ASCII-8BIT ✓ "uXXXX" 表記を含む場合は UTF-8 # coding: us-ascii /a/.encoding #=> #<Encoding:US-ASCII> /x41/.encoding #=> #<Encoding:US-ASCII> /xFF/.encoding #=> #<Encoding:ASCII-8BIT> /u3042/.encoding #=> #<Encoding:UTF-8> 30/45Rubyのエンコーディング - NSEG#30 Powered by Rabbit 1.0.9
  32. 32. はまり どころRubyのエンコーディング - NSEG#30 31/45 Powered by Rabbit 1.0.9
  33. 33. 文字列比較 文字が等しくてもエンコーディングが異なれば異なる u = "あ".encode("utf-8") s = "あ".encode("cp932") u == s #=> false 32/45Rubyのエンコーディング - NSEG#30 Powered by Rabbit 1.0.9
  34. 34. 文字列比較 バイト列が等しくてもエンコーディングが異なれば異 なる # coding: utf-8 u = "あ" b = "あ".force_encoding("ascii-8bit") u == b #=> false 33/45Rubyのエンコーディング - NSEG#30 Powered by Rabbit 1.0.9
  35. 35. 文字列比較 エンコーディングが異なっていてもASCII互換のエン コーディングでASCII文字だけなら比較できる # coding: utf-8 u = "abc".encode("utf-8") s = "abc".encode("cp932") u == s #=> true 34/45Rubyのエンコーディング - NSEG#30 Powered by Rabbit 1.0.9
  36. 36. 正規表現 エンコーディングが異なっていたらエラー # coding: utf-8 "あ" =~ /./s # incompatible encoding regexp match (Windows-31J regexp # with UTF-8 string) (Encoding::CompatibilityError) 35/45Rubyのエンコーディング - NSEG#30 Powered by Rabbit 1.0.9
  37. 37. 正規表現 ASCII文字だけならエラーにならない # coding: utf-8 "ABC" =~ /./s ASCII文字だけでテストしたりすると本番で落ちたり 36/45Rubyのエンコーディング - NSEG#30 Powered by Rabbit 1.0.9
  38. 38. 文字列結合 異なるエンコーディング同士の結合はエラー u = "あ".encode("utf-8") s = "あ".encode("cp932") u + s # incompatible character encodings: UTF-8 and Windows-31J # (Encoding::CompatibilityError) 37/45Rubyのエンコーディング - NSEG#30 Powered by Rabbit 1.0.9
  39. 39. 文字列結合 ASCII文字だけならエラーにならない u = "ABC".encode("utf-8") s = "DEF".encode("cp932") u + s #=> "ABCDEF" (UTF-8) 38/45Rubyのエンコーディング - NSEG#30 Powered by Rabbit 1.0.9
  40. 40. リテラル スクリプトエンコーディングに合わない文字があると スクリプトのロード時にエラー # coding: cp932 "あ" # UTF-8の「あ」 # invalid multibyte char (Windows-31J) 39/45Rubyのエンコーディング - NSEG#30 Powered by Rabbit 1.0.9
  41. 41. リテラル でも "xHH" 表記だとエラーにならない # coding: cp932 "xE3x81x82" # UTF-8の「あ」 40/45Rubyのエンコーディング - NSEG#30 Powered by Rabbit 1.0.9
  42. 42. 不正な文字 正規表現との比較でエラー # coding: cp932 str = "xE3x81x82" # ここではエラーにならない str =~ /./ # invalid byte sequence in Windows-31J (ArgumentError) 41/45Rubyのエンコーディング - NSEG#30 Powered by Rabbit 1.0.9
  43. 43. 不正な文字 エンコーディングがあってたとしても不正な文字は発 生しうる # 不正な文字が入っているファイルをUTF-8指定で読んでしまった File.open("utf-8.txt", "r:utf-8").gets # エラーにはならない UTF-8 エンコーディングの文字列が得られるが、不 正な文字が含まれているかもしれない 42/45Rubyのエンコーディング - NSEG#30 Powered by Rabbit 1.0.9
  44. 44. 変換 内部エンコーディングを指定すると不正な文字で変 換エラー # CP932だけど不正な文字が入ってる f = File.open("cp932.txt", "r:cp932:utf-8") f.gets # 不正な文字が含まれる行でエラー # `gets: "xFCxA1" from Windows-31J to UTF-8 # (Encoding::UndefinedConversionError) 43/45Rubyのエンコーディング - NSEG#30 Powered by Rabbit 1.0.9
  45. 45. 変換 ✓ 外部エンコーディングを指定してないと環境変 数の影響うけるかも ✓ 内部エンコーディング指定すると自動的に変 換されるけど、読むだけでエラーになるかも 44/45Rubyのエンコーディング - NSEG#30 Powered by Rabbit 1.0.9
  46. 46. まとめ ✓ 文字単位の処理は便利 ✓ ハマる時はハマる ✓ データのエンコーディングを統一するのが吉 45/45Rubyのエンコーディング - NSEG#30 Powered by Rabbit 1.0.9

×