文字コードのお話

5,745 views

Published on

社内勉強会の資料
http://blog.flect.co.jp/labo/2012/10/post-7bb1.html

0 Comments
10 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
5,745
On SlideShare
0
From Embeds
0
Number of Embeds
135
Actions
Shares
0
Downloads
30
Comments
0
Likes
10
Embeds 0
No embeds

No notes for slide

文字コードのお話

  1. 1. 2012/10/01株式会社FLECT
  2. 2.  開発者が文字化けなど文字コード関連の問題に直面し た時にその原因がなんとなく予想できるようになるこ とを最大の目的とする 正確で厳密な説明をすることは目標としない ◦ 何故なら書いている人にその能力がないから。 ◦ 正確な情報を書こうとしても時間の経過とともに変わること もあるし、(例、JIS X 208の文字数) ◦ 枠組みさえ押さえておけば細かい部分は知らなくても上の目 的は達成できるはず。 技術的な内容のみを述べ文化的な話には立ち入らない ◦ 包摂規準等も対象外 要するにこの文書に書いていることを鵜呑みにしてはいけない
  3. 3.  世界中にどれだけの文字があるのか知っている人 が世の中にいないから ◦ 日本語、英語、中国語、韓国語、タイ語、etc..etc…。 メジャーな言語だけでもたくさんある ◦ 日本語ひとつとっても、歴史学者が古典にしか出現しな い文字を必要と主張したりするし、 ◦ さらに異体字とかあったり、 (例、高と髙(ハシゴダカ)) ◦ 最近では絵文字も文字と認定されてしまった 言語、歴史、文化など様々な立場がクロスするためある意 味 正解のない問題と言える
  4. 4.  歴史をおさえる 日本語コード体系(いわゆるJIS)とUnicodeの違い をおさえる 文字集合とエンコーディングスキームをちゃんと 区別する Shift_JISとWindows-31J(MS932)を見極める ◦ 多くの処理系が「Shift_JIS」と言いながら実はMS932を 使用しているため注意が必要これでほとんどの文字化けは説明できる
  5. 5.  1バイトの文字は直線で表す 2バイトの文字は正方形で表す ◦ 縦軸が1byte目(Lead-Byte) ◦ 横軸が2byte目(Trailer-Byte) それ以外は文章で補足 FF FF 80 80 256 * 256 = 65536 128個の 128*128 = 16384 ポイント 00 00 80 FF
  6. 6.  わずか94文字(SP,CR,LF等は除く) ◦ 英大文字、小文字、数字、記号 つまり1文字を表すのに7bitで十分 ◦ 8bit目は常に0 ◦ このように8bit目を使用しない文字コードを「7bitの文字コード」と言 う ◦ 過去には8bit目に独自の意味づけをするアプリもあったらしい Ex.) 8bit目が「1」の場合はその文字を赤く表示するなど ◦ SMTPサーバーは本来7bitの文字コードしか通さない FF FF 80 80 94文字を 定義 00 00 80 FF
  7. 7.  US-ASCIIの未使用領域に半角カナを配置 同じ成り立ちの文字コードとしてヨーロッパ圏で 使用されるIS0-8859-1などがある 0x5CはBACK-SLASHからYEN-MARKに変更 FF FF いわゆる半角カナ (0x9F以前と0xE0以降 は未使用) 80 80 US-ASCII (ただし0x5C=) 00 00 80 FF
  8. 8.  まったく新しい文字セットを94 * 94の領域に定義 ◦ つまりすべての文字は2バイト文字 ◦ 英数字、カタカナにも新しい区点を付与 このためそれらの文字はUS-ASCII、JIS X 201とは別のコードポイント (いわゆる全角文字) ◦ 定義領域を94 * 94としたのは7bitの範囲で収まるようにしたかったか ら 実際に定義された文字は約6900文字 ◦ 数回の改定で文字が追加されたり字形が変わったりしている ◦ 逆に言うと1900文字分程度の未使用領域がある FF FF 0x21 – 0x7E 80 80 94*94=8836 00 00 80 FF
  9. 9.  そのまま使うと既存のコード体系(US-ASCII、JIS X 201)との互換性がない しかし既にそれらの資産があるのでどうにかして互換 性を維持したい ◦ これは日本固有の問題ではなく世界中(主に中国と韓国)で同じ ような課題に直面していた エンコーディングスキームの必要性
  10. 10.  文字コード = 文字集合 + エンコーディングスキーム ◦ エンコーディングスキームの訳は「文字符号化方式」だがあまりピンと来 ないのでここではエンコーディングスキームという用語を使用する ◦ 文字コードの厳密訳は「符号化文字集合」らしい 文字集合 ◦ ある文字コードに含まれる文字として何があるかを定義したもの (例えば「五十音」は文字集合) エンコーディングスキーム ◦ ある文字集合(複数の場合もある)をどのように符号化するかを定義したもの (五十音のエンコーディングスキームとして「ひらがな」と「かたかな」が ある) JISの場合 ◦ 文字集合: JIS X 201, JIS X 208, JIS X 212, JIS X 213 ◦ エンコーディングスキーム: Shift_JIS, EUC-JP, iso-2022-jp Unicodeの場合 ◦ 文字集合: Unicode ◦ エンコーディングスキーム: UTF-8, UTF-16
  11. 11.  シフトコードによって文字集合を切り替えるエンコーディング スキーム ◦ 「1B 24 42」が現れたらその先はJIS X 208 ◦ 「1B 28 42」が現れたらその先はUS-ASCII 使える文字集合はUS-ASCIIとJIS X 208 ◦ つまり JIS X 201(半角カナ)は仕様上使えない ◦ 。。。はずなんだが最近の処理系はほとんど「1B 28 49」でJIS X 201 に切り替わっているらしい(試してみたらJDK6でもそうなっててちょっ とびっくりした) 何故これがメールで使われるかというと7bitの文字コードだか FF ら FF 80 80 00 シフトコード 00 80 FF による切替
  12. 12.  基本は7bit * 7bitの範囲で定義された2byteの文字集合の両方のbyteを 0x80以降にずらすと考えると良い ◦ つまり0x7F以下は1バイト文字、0x80以上はマルチバイト文字となる ◦ このためJIS X 201の半角カナはそのままでは使えない さらにシングルシフトという仕組みでより多くの文字集合を扱うこと ができる ◦ シングルシフトとは特定のbyteが現れたらそれに続く1byteまたは2byteは別の文 字集合として解釈する仕組み ◦ 「8E」が現れたらそれに続く1byteはJIS X 201。つまりEUCでは半角カナは 2byte文字 ◦ 「8F」が現れたらそれに続く2byteはJIS X 212(後述)。つまり1文字が3byteと なる仕様上使える文字集合はJIS X 201, JIS X 208, JIS X 212だが、昔は 3byte文字や2byteの半角カナを正しく扱えるアプリケーションはほと FF FF んどなかったので実質JIS X 208しか使えなかった。(今はどうだか知ら半角カナは ないが)シングルシフトで対応 80 80 00 00 80 FF
  13. 13.  JIS X 201で作成された文書との完全な互換性を持つことを目的とした 日本独自のエンコーディングスキーム ◦ 1byte目がJIS X 201の空き領域(0x9F以前と0xE0以降)の場合の2byte目の領域に JIS X 208の文字を再配置 ◦ JISコードをずらす(Shift)ことによってできた文字コードなのでShift_JISと言う 2byte目に0x7F以下のbyteが現れるため扱いの難しいコード体系と なっている 厳密な意味でのShift_JISの文字集合はJIS X 201とJIS X 208のみなので 丸数字などのいわゆる機種依存文字は含まれない FF FF いわゆる半角カナ (0x9F以前と0xE0以降 は未使用) 80 80 00 00 80 FF
  14. 14.  Shift_JISの空き領域にIBMやNECが独自に追加した文字(いわ ゆる機種依存文字)をMicrosoftが統合したもの ◦ 代表的な文字は丸数字やローマ数字など ◦ JIS X 208ではなくShift_JISの拡張である点が話をややこしくして いる 「Windows-31J」という名前はIANAに登録されているが非 推奨 ◦ このため多くの処理系が「Shift_JIS」という名前でWindows-31J を扱っている FF FF ◦ Javaは両者を厳密に区別しているのがかえって迷惑(-- いわゆる半角カナ (0x9F以前と0xE0以降 機種依存文字 は未使用) 80 80 00 00 80 FF
  15. 15.  7bit * 7bitの範囲に定義された文字集合 ◦ JIS X 208から漏れた文字を補完する目的なのでJIS X 208との重複はない ◦ 定義されている文字は約6000文字 EUC-JP,またはUnicodeで使用可能 ◦ ISO-2022-JP-1(2)というのもあるらしいが本当に実装があるのかは謎 ◦ UnicodeのコードポイントはBMP(非サロゲートペア)の範囲 ◦ EUC(3byte文字)を正しく扱えない処理系はまだありそうなのでUnicode 以外では使わない方が無難 FF FF 80 80 00 00 80 FF
  16. 16.  JIS X 208を拡張する形で再定義された文字集合 ◦ JIS X 208のすべての文字を含む ◦ MS932との整合性が考慮されている(外字領域がないなど完全で はない) ◦ JIS X 212との重複はある エンコーディングスキームも同時に定義 ◦ Shift_JIS, EUC, ISO-2022のそれぞれでのエンコーディングス キームも規定されたが多分実装されていない ◦ Unicodeでは使用可能だが一部の文字はサロゲートペアとなる FF FF 80 80 2面を追加 してさらに 文字を追加 00 00 80 FF JIS X 208の空き領域に文字を追加
  17. 17.  おそらくMS932をベースにキャリアが独自に絵文 字を追加 ◦ とても迷惑 ◦ 当然キャリア間での互換性はない ◦ キャリア間ではサーバーでコード変換を行っている(受信 側か送信側かは不明) Unicode 6.0で絵文字も文字コードに追加された ◦ とても迷惑 ◦ 今のところPCへのメール送信でコード変換されている気 配はない(Unicodeではなくiso-2022-jpでの送信) ◦ このまま黒歴史として葬ってもらいたい
  18. 18.  本来仕様でサポートされない文字は化けるのが正しい ◦ MS932の機種依存文字 ◦ EUC-JPのJIS X 212 ◦ ISO-2022-JPに半角カナはない JISコード間では機械的な可逆変換が可能 ◦ 典型的な例としてメールで  送信側ユーザーのメール作成画面でMS932を使用  メール送信時にISO-2022-JPに変換  受信側ユーザーのメール表示画面で再度MS932に変換 ◦ としていた場合、変換アルゴリズムが同じであれば文字化け なしで元の文章が復元されることはありうる JISとUnicodeの変換では必ず変換テーブルが必要 ◦ Javaはコード変換時に一度Unicodeになるので必ず化ける
  19. 19.  ISO-2022-JP ◦ いつの間にやら半角カナ用のシフトコードがある(どうもOutlook が始めたことを他が追随したらしい) ◦ Java6から「x-windows-iso2022jp」というMS932ベースの ISO-2022-JPという謎のエンコーディングをサポート Shift_JIS ◦ 世の中的にはほぼ間違いなくMS932のこと 現状丸数字などは当たり前のように(ISO-2022-JPの)メールで使用 されていたりするのでもはやそれを使うなという説明に理解が得ら れ るとは考えにくい Javaの場合は起動時のオプションで -Dsun.nio.cs.map=x-windows-iso2022jp/ISO-2022-JP -Dsun.nio.cs.map=Windows-31J/Shift_JIS としてエンコーディング名を差し替えた方が幸せになれ るかも
  20. 20.  世界中の文字をすべて一つのコード体系の中に押 し込めようという壮大な計画 ◦ JISは日本人が日本語のためだけに作成したコード体系な ので成り立ちが全く異なる 当初は2byteの範囲(256*256=65536文字)に全 ての文字を収めようとしていた ◦ あっさり破綻してサロゲートペアという仕組みを導入 JISの文字集合としては以下を収録 ◦ JIS X 201 ◦ JIS X 208 ◦ JIS X 212 ◦ JIS X 213
  21. 21.  1991/10 Ver 1.0 1996/7 Ver 2.0 サロゲートペア導入 2002/3 Ver 3.2 JIS X 213対応 2010/10 Ver 6.0 絵文字追加2012年9月現在のバージョンは6.1あとは文字が増えるだけ
  22. 22.  BMP(0x0000 – 0xFFFF) UTF16で2byteで表現できる文字 ◦ 第0面とも言う ◦ UTF-16のサロゲートペアとなる領域(0xD800 – 0xDFFF)には文字 を定義できない 拡張領域(0x1_0000 – 0x10_FFFF)サロゲートペアとなる文 字 ◦ 第1面 ~ 第16面FF FF × 1680 80 100万文字以上00 80 FF 00 80 FF 収録可能 BMP 拡張領域 Ver 6.1現在 11万文字定義済み
  23. 23.  US-ASCIIと互換性のあるエンコーディングスキーム ◦ 0x00 – 0x7F (7bitまで)  1byte文字そのまま ◦ 0x80 – 0x7FF(11bitまで)  2byte  110xxxxx – 10xxxxxxx ◦ 0x800 – 0xFFFF (16bitまで)  3byte  1110xxxx – 10xxxxxx – 10xxxxxx ◦ 0x1_0000 – 0x1F_FFFF (21bitまで)  4byte  11110xxx – 10xxxxxx – 10xxxxxx – 10xxxxxx  実際にはUnicodeのコード領域は0x10_FFFFまで ◦ BMPはすべて3byteに収まるが拡張領域の文字は4byteになる
  24. 24.  BMPの文字はコードポイントそのまま 拡張領域の文字はサロゲートペアとなる ◦ 上位サロゲートの範囲は0xD800 – 0xDBFF (1024個) ◦ 下位サロゲートの範囲は0xDC00 – 0xDFFF (1024個) ◦ 1024 * 1024 = 1,048,576( = 65536 * 16)文字 サロゲートペアをサポートする場合1文字2byte固 定ではないので注意が必要 ◦ JavaのCharacterとStringはUTF-16ベースの実装  String#lengthはUTF16のワード数を返す  String#codePointCountは文字数を返す
  25. 25.  Unicodeでは複数のコードポイントで1文字を表 す仕組みがある ◦ 「が(U+304C)」を「か(U+304B)」+「゛(U+3099)」 とも書ける Windowsでは結合文字を見かけることはほとんど ない(尐なくとも日本では) Mac OS Xではファイル名などに含まれる分解可 能な文字は積極的に分解されるらしい(未検証) ◦ 要するに「が」は常にU+304B U+3099の並びになる Webフォームやメールからの添付ファイルを扱う 場合には正規化が必要かも? ◦ しかしあまり問題になったという話を聞かないので一般 の人はほとんど気がつかないんだろうと思う
  26. 26. 表1:Unicode変換先のコードポイント  Shift_JIS <-> Unicodeの変換テーブルと MS932 <-> Unicodeの変換テーブルで いくつかの記号のマッピングが異なる 元の文字 Shift_JISで変換 MS932で変換 ~(WAVE DASH) U+301C U+FF5E ∥(DOUBLE VERTICAL LINE) U+2016 U+2225 -(MINUS SIGN) U+2212 U+FF0D ¢(CENT SIGN) U+00A2 U+FFE0 £(POUND SIGN) U+00A3 U+FFE1 ¬(NOT SIGN) U+00AC U+FFE2 この問題の対処にも-Dsun.nio.cs.map=…の対処が有効
  27. 27.  PostgreSQL 8.2.2以降対応 MySQL 5.5.3以降 ◦ DB作成時にcharactersetを「utf8mb4」とする必要が ある Salesforce NG IE9 OK Chrome 21 OK Firefox 15 OK Safari 5.1.7 NG(Windows版だけかも?) ◦ Macの最新版は6なのでWindows版は開発終了との噂も iOS6 OK
  28. 28.  特に理由がない限りUTF-8でページを返すのが無 難 ガラケーサイトはShift_JISで作成するしきたり ◦ 慣習に従って「Shift_JIS」と言っているが実際には MS932 ◦ 最近の端末はほとんどUTF-8を解釈しているっぽいが ◦ 古い端末では化けるモノもあるらしい ◦ Playframeworkではこんな問題も ◦ http://blog.flect.co.jp/labo/2012/08/playframewor k-5a1c.html (次バージョンで修正される予定)
  29. 29.  元々はSMTPが7bitの文字しか通さない仕様だったため ISO-2022-JPが使用されていた その後MIMEの導入で8bitの文字コードを7bitにエンコー ドして送信することが可能になったのでISO-2022-JPにこ だわる必然性はなくなったが、いまだにその慣習が根強く 残っている ◦ 昔はISO-2022-JPのメールしか処理ができないくさったメールク ライアントも多かった 個人的にはメールもUTF-8で送っても良いんじゃないかと は思っているが。。。 ◦ いまだにUTF-8を処理できないメールクライアントが残っている 可能性はあるのでリスクはある ◦ (主に携帯関連の処理で)中継サーバーがコード変換を行っている ことも多い気もするし、そうするとあんまり意味がない。 ◦ MS932互換のISO-2022-JPが事実上の標準として幅を利かして いるのであればもうそれで良いんじゃないかという気もする。 ◦ 絵文字対応が可能になるのもヤブヘビだし。

×