Rubyのエンコーディング
                             NSEG#30

                          とみたまさひろ
                             2012-08-25




Rubyのエンコーディング - NSEG#30        Powered by Rabbit 1.0.9
自己紹介

      ✓ とみた まさひろ (ペンネーム)
      ✓ プログラマー (Ruby & C)
      ✓ http://d.hatena.ne.jp/tmtms
      ✓ http://twitter.com/tmtms
      ✓ 好きなもの
           ✓ Ruby, MySQL, Ubuntu, Emacs, Git


                                                             1/45
Rubyのエンコーディング - NSEG#30                        Powered by Rabbit 1.0.9
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
Ruby 1.8
        は
      オワコン
Rubyのエンコーディング - NSEG#30
                                        3/45
                          Powered by Rabbit 1.0.9
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/45
Rubyのエンコーディング - NSEG#30                                            Powered by Rabbit 1.0.9
Ruby 1.9
   を使いまし
     ょう
Rubyのエンコーディング - NSEG#30
                                        5/45
                          Powered by Rabbit 1.0.9
1.9の
          特徴
Rubyのエンコーディング - NSEG#30
                                        6/45
                          Powered by Rabbit 1.0.9
一番大きい
  のはエンコ
  ーディング
Rubyのエンコーディング - NSEG#30
                                        7/45
                          Powered by Rabbit 1.0.9
Rubyのエンコーディング
      http://d.hatena.ne.jp/tmtms/20120812/ruby_encoding




                                                                         8/45
Rubyのエンコーディング - NSEG#30                                    Powered by Rabbit 1.0.9
エンコーディング?

      ✓ 文字符号化方式
      ✓ UTF-8 とか EUC-JP とか SHIFT_JIS とか
        そーゆー奴
      ✓ charset とか呼ばれたり
      ✓ いわゆる「文字コード」


                                                    9/45
Rubyのエンコーディング - NSEG#30               Powered by Rabbit 1.0.9
同じ文字でも異なるコード


      「あ」
      ✓ UTF-8 では 0xE3 0x81 0x82 の3バイト
      ✓ EUC-JP では 0xA4 0xA2 の2バイト
      ✓ SHIFT_JIS では 0x82 0xA0 の2バイト



                                                   10/45
Rubyのエンコーディング - NSEG#30                Powered by Rabbit 1.0.9
同じバイト列でも別の文字


      0xC2 0xA9 の2バイトは
      ✓ UTF-8 では「©」1文字
      ✓ EUC-JP では「息」1文字
      ✓ SHIFT_JIS では「ツゥ」2文字



                                          11/45
Rubyのエンコーディング - NSEG#30       Powered by Rabbit 1.0.9
Ruby 1.8.x


      ✓ "xC2xA9" という文字列は Ruby 的にはた
        だのバイト列
      ✓ エンコーディング情報を持たない
      ✓ "©"(UTF-8) として扱うか "息"(EUC-JP) とし
        て扱うかはプログラム次第



                                                   12/45
Rubyのエンコーディング - NSEG#30                Powered by Rabbit 1.0.9
Ruby 1.9.x
      ✓ 文字列のエンコーディングは文字列自身が知
        っている
      ✓ "©"(UTF-8) と "息"(EUC-JP) は同じバイト列
        だけど異なる文字列
      ✓ "あ"(UTF-8) と "あ"(EUC-JP) は同じ文字を表
        してるけど等しくない
      ✓ 同じプログラム中で複数のエンコーディングの
        文字列を同時に扱える(珍しいかも)

                                                   13/45
Rubyのエンコーディング - NSEG#30                Powered by Rabbit 1.0.9
ちゃんと文字として扱える

                # Ruby 1.8.7
                "文字".size       #=>   6
                "文字".bytesize   #=>   6
                "文字"[0]         #=>   230 (0xE6)
                "文字".reverse    #=>   "??????"
                # Ruby 1.9.3
                "文字".size       #=>   2
                "文字".bytesize   #=>   6
                "文字"[0]         #=>   "文"
                "文字".reverse    #=>   "字文"
                                                           14/45
Rubyのエンコーディング - NSEG#30                        Powered by Rabbit 1.0.9
String#encoding



    文字列のエンコーディングを調べる

           "あ".encoding #=> #<Encoding:UTF-8>




                                                        15/45
Rubyのエンコーディング - NSEG#30                     Powered by Rabbit 1.0.9
String#encode


    エンコーディング変換

             str = "あ"
             str.encoding   #=> #<Encoding:UTF-8>
             str2 = str.encode("cp932")
             str2.encoding #=> #<Encoding:Windows-31J>




                                                               16/45
Rubyのエンコーディング - NSEG#30                            Powered by Rabbit 1.0.9
エンコーディングは何で決まる?


      ✓ スクリプトエンコーディング
      ✓ 外部エンコーディング
      ✓ 内部エンコーディング




                                      17/45
Rubyのエンコーディング - NSEG#30   Powered by Rabbit 1.0.9
スクリプトエンコーディング

      ✓ スクリプト中の文字列リテラルのエンコーディ
        ングを決定する
      ✓ スクリプト先頭行のマジックコメントで指定する

              # coding: utf-8
              "あ".encoding #=> #<Encoding:UTF-8>

      ✓ デフォルトは US-ASCII (または -K で指定)

                                                        18/45
Rubyのエンコーディング - NSEG#30                     Powered by Rabbit 1.0.9
スクリプトエンコーディング

      ✓ 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/45
Rubyのエンコーディング - NSEG#30                                  Powered by Rabbit 1.0.9
外部エンコーディング
      ✓ ファイル内の文字列が何のエンコーディングか
        を指定する
      ✓ File.open 時に指定する

              f = File.open("file.txt", "r:utf-8")
              f.gets # UTF-8文字列
           ✓ ファイルの内容は UTF-8
           ✓ 読み込んだ文字列も UTF-8 エンコーディング

                                                         20/45
Rubyのエンコーディング - NSEG#30                      Powered by Rabbit 1.0.9
外部エンコーディング(書き込み)



           f = File.open("file.txt", "w:utf-8")
           f.puts("ほげ")

    ✓ 文字列が UTF-8 に変換されて書き込まれる



                                                        21/45
Rubyのエンコーディング - NSEG#30                     Powered by Rabbit 1.0.9
内部エンコーディング
      ✓ ファイルから読み込んだ文字列のエンコーディ
        ングを変換する
      ✓ File.open 時に指定する

            File.open("file.txt", "r:cp932:utf-8")
           ✓ ファイルの内容は CP932
           ✓ 読み込んだ文字列は UTF-8 エンコーディング
           ✓ 書き込み時はあまり関係ない
                                                        22/45
Rubyのエンコーディング - NSEG#30                     Powered by Rabbit 1.0.9
もうちょっ
 と詳しく                                 23/45
Rubyのエンコーディング - NSEG#30   Powered by Rabbit 1.0.9
読み込み時の変換
      ✓ メソッドによって変換したりしなかったり
      ✓ バイナリ読み込みメソッド(常に ASCII-8BIT)
           ✓ read(n) / read_nonblock / readpartial /
             sysread

      ✓ テキスト読み込みメソッド
           ✓ foreach / readlines / each_line / lines /
             gets / getc / ungetc / read / readchar /
             readline / readlines

                                                                24/45
Rubyのエンコーディング - NSEG#30                             Powered by Rabbit 1.0.9
外部エンコーディング未指定時

    読み込み時は 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/45
Rubyのエンコーディング - NSEG#30                              Powered by Rabbit 1.0.9
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/45
Rubyのエンコーディング - NSEG#30                                          Powered by Rabbit 1.0.9
書き込み時の変換

      ✓ メソッドには依らない
      ✓ IO に外部エンコーディングが指定されていた
        場合は変換される
      ✓ 外部エンコーディングが ASCII-8BIT の場合
        は変換されない
      ✓ 外部エンコーディングが指定されていない場
        合は変換されない(基本的には)

                                                 27/45
Rubyのエンコーディング - NSEG#30              Powered by Rabbit 1.0.9
正規表現
  のエンコー
   ディング
Rubyのエンコーディング - NSEG#30
                                      28/45
                          Powered by Rabbit 1.0.9
正規表現リテラル

      ✓ 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/45
Rubyのエンコーディング - NSEG#30                                  Powered by Rabbit 1.0.9
正規表現リテラル

      ✓ 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/45
Rubyのエンコーディング - NSEG#30                                  Powered by Rabbit 1.0.9
はまり
         どころ
Rubyのエンコーディング - NSEG#30
                                      31/45
                          Powered by Rabbit 1.0.9
文字列比較


    文字が等しくてもエンコーディングが異なれば異なる

                          u = "あ".encode("utf-8")
                          s = "あ".encode("cp932")
                          u == s    #=> false



                                                                32/45
Rubyのエンコーディング - NSEG#30                             Powered by Rabbit 1.0.9
文字列比較

    バイト列が等しくてもエンコーディングが異なれば異
    なる

          #   coding: utf-8
          u   = "あ"
          b   = "あ".force_encoding("ascii-8bit")
          u   == b     #=> false


                                                        33/45
Rubyのエンコーディング - NSEG#30                     Powered by Rabbit 1.0.9
文字列比較

    エンコーディングが異なっていてもASCII互換のエン
    コーディングでASCII文字だけなら比較できる

                      #   coding: utf-8
                      u   = "abc".encode("utf-8")
                      s   = "abc".encode("cp932")
                      u   == s     #=> true


                                                                34/45
Rubyのエンコーディング - NSEG#30                             Powered by Rabbit 1.0.9
正規表現


    エンコーディングが異なっていたらエラー

          # coding: utf-8
          "あ" =~ /./s
          # incompatible encoding regexp match (Windows-31J regexp
          # with UTF-8 string) (Encoding::CompatibilityError)




                                                                         35/45
Rubyのエンコーディング - NSEG#30                                      Powered by Rabbit 1.0.9
正規表現


    ASCII文字だけならエラーにならない

                          # coding: utf-8
                          "ABC" =~ /./s

    ASCII文字だけでテストしたりすると本番で落ちたり


                                                        36/45
Rubyのエンコーディング - NSEG#30                     Powered by Rabbit 1.0.9
文字列結合


    異なるエンコーディング同士の結合はエラー

          u   = "あ".encode("utf-8")
          s   = "あ".encode("cp932")
          u   + s
          #   incompatible character encodings: UTF-8 and Windows-31J
          #   (Encoding::CompatibilityError)




                                                                           37/45
Rubyのエンコーディング - NSEG#30                                        Powered by Rabbit 1.0.9
文字列結合


    ASCII文字だけならエラーにならない

                   u = "ABC".encode("utf-8")
                   s = "DEF".encode("cp932")
                   u + s #=> "ABCDEF" (UTF-8)



                                                            38/45
Rubyのエンコーディング - NSEG#30                         Powered by Rabbit 1.0.9
リテラル

    スクリプトエンコーディングに合わない文字があると
    スクリプトのロード時にエラー

         # coding: cp932
         "あ"     # UTF-8の「あ」
         # invalid multibyte char (Windows-31J)


                                                       39/45
Rubyのエンコーディング - NSEG#30                    Powered by Rabbit 1.0.9
リテラル


    でも "xHH" 表記だとエラーにならない

              # coding: cp932
              "xE3x81x82"    # UTF-8の「あ」



                                                      40/45
Rubyのエンコーディング - NSEG#30                   Powered by Rabbit 1.0.9
不正な文字


    正規表現との比較でエラー

          # coding: cp932
          str = "xE3x81x82" # ここではエラーにならない
          str =~ /./
            # invalid byte sequence in Windows-31J (ArgumentError)




                                                                         41/45
Rubyのエンコーディング - NSEG#30                                      Powered by Rabbit 1.0.9
不正な文字


    エンコーディングがあってたとしても不正な文字は発
    生しうる

         # 不正な文字が入っているファイルをUTF-8指定で読んでしまった
         File.open("utf-8.txt", "r:utf-8").gets # エラーにはならない


    UTF-8 エンコーディングの文字列が得られるが、不
    正な文字が含まれているかもしれない


                                                                  42/45
Rubyのエンコーディング - NSEG#30                               Powered by Rabbit 1.0.9
変換

    内部エンコーディングを指定すると不正な文字で変
    換エラー

          # CP932だけど不正な文字が入ってる
          f = File.open("cp932.txt", "r:cp932:utf-8")
          f.gets   # 不正な文字が含まれる行でエラー
          # `gets': "xFCxA1" from Windows-31J to UTF-8
          # (Encoding::UndefinedConversionError)



                                                               43/45
Rubyのエンコーディング - NSEG#30                            Powered by Rabbit 1.0.9
変換


      ✓ 外部エンコーディングを指定してないと環境変
        数の影響うけるかも
      ✓ 内部エンコーディング指定すると自動的に変
        換されるけど、読むだけでエラーになるかも



                                           44/45
Rubyのエンコーディング - NSEG#30        Powered by Rabbit 1.0.9
まとめ


      ✓ 文字単位の処理は便利
      ✓ ハマる時はハマる
      ✓ データのエンコーディングを統一するのが吉




                                            45/45
Rubyのエンコーディング - NSEG#30         Powered by Rabbit 1.0.9

Rubyのエンコーディング

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