Ruby Freaks Lounge

第4回Ruby M17N 事始め:文字コード編

はじめに

今回は文字列を扱う際には忘れてはならない文字コードについて、日本人が知っておくべきエンコーディングを中心に解説していきます。

US-ASCII

ASCIIは、ASA(American Standards Association、のちにUSASIを経てANSI)によって、1963年6月17日にASA X3.4-1963として制定され、1967年7月7日にUSASI(United States of America Standards Institute、ASAから1966年8月24日に改組)によってUSAS X3.4-1967へと改訂されてほぼ現在の形となりました。

その後の多くの文字コードがASCIIのスーパーセットとして作られたため、ASCIIは共通のサブセットとして特別な位置に置かれるようになりました。RubyでもASCIIに含まれる文字のみで構成されるStringは、ASCII互換エンコーディングに結合できる等、特別な扱いをしています。

ASCII-8BIT

ASCII-8BITは「ASCII互換オクテット列」に与えられるエンコーディングです。 言い換えると、一般的な「文字列」とは異なっているが、バイナリとも異なり ASCII 互換であるということです。 つまり、後で述べる ASCII 非互換なエンコーディングな文字列と異なり、ASCII のみの文字列と結合・比較等を行うことが可能です。なお、Ruby 1.9.1 では ASCII 非互換なバイナリエンコーディングは必要性がないと思われたので用意されていません。

シフトJIS

シフトJISは日本でもっとも広く栄えた文字コードと言えるでしょう。しかし、その生い立ちについては不確かな説が飛び交い、長らく深い霧の向こうにありました。最近の元マイクロソフト株式会社会長の古川享や中心的な役割を果たした山下良蔵の証言によると三菱電機とアスキーマイクロソフト、およびマイクロソフトが開発し、マイクロソフトウェア・アソシエイツが命名したのが「シフトJIS」となるようです。

Shift_JIS

IANA Character Setsにpreferred MIME nameとして登録されている名前で、他にaliasとしてMS_KanjiとcsShiftJISが登録されています。内容としてはJIS X 0208:1997 附属書1で規定された「シフト符号化表現」を参照しています。

Windows-31J

Windows 3.1 日本語版のリリースに際して、MicrosoftはWindows Codepage 932の仕様の統一を図り、ベンダごとに異なっていた文字集合を統一することにしました。具体的には、JIS X 0201とJIS X 0208に、有力なベンダであったNECとIBMのベンダ外字であるNEC特殊文字、IBM拡張文字、NEC選定IBM拡張文字を加えたものと定めています。IANA Character Setsにもpreferred MIME nameとして登録されていますが、HTML等でこれを用いたい場合は、IEではAliasであるcsWindows31Jを用いないと認識しません(しかし、Firefox 3.0はcsWindows31Jを認識しないため、結局使えない⁠⁠。なお、IBM CP943が文字集合としてはこれと一致しています。また、JavaではこれをMS932と呼んでいます。

Unicodeとの変換に際して、Shift_JISとWindows-31Jでは変換表の内容が異なります。具体的には0x5Cや0x7Eに加え、0x8160等の対応が異なっています波ダッシュ問題⁠。WindowsのシフトJISをUnicodeへと変換する際には、必ずWindows-31Jを指定するようにしましょう。

MacJapanese

Mac OS 7.1からMac OS 9までの間に、日本語用として用いられていたエンコーディングです。Ruby 1.9.1ではUnicodeへの変換には対応していません。

日本語EUC

日本語EUCは、日本語UNIXシステム諮問委員会が原形を作り、AT&Tが他言語用に一般化してEUCと名付けた文字コードです。

日本語UNIXシステム諮問委員会は、1984年8月にAT&T Unix Pacificの要請に基づき、東京大学、NTT、富士通、日立、三菱、NEC、沖、東芝、AT&T Unix Pacificをメンバーとし、2009年3月9日に亡くなられた石田晴久東大教授(当時)を委員長として設置されました。また、下部組織として、図書館情報大学、東京大学、東京工業大学、NTT、東芝、AT&T UNIX Pacificによる日本語UNIXシステム検討会が作られ、詳細仕様の作成を行いました。委員会は議論の結果をまとめ、1985年4月にAT&T Unix PacificへとUNIXシステム日本語機能提案書を答申します。ここで定義された「日本語用UNIX内部コード体系」が、日本語EUCの原形となりました。

これをAT&T Unix Pacificが中国語や韓国語でも用いることができるように一般化したものがExtended Unix Code、略してEUCです。日本語EUCはSystem V Release 2.0用の拡張である、Japanese Application Environment Release 1.0に実装されて1985年に公開されました。

その後、JIS X 0212で補助漢字が規定されたことに伴い、JIS X 0212研究会での議論を経て、1991年12月12日「UI-OSF-USLP 共同技術資料:日本語EUC の定義と解説」が公開されました。この規格では従来外字が割り当てられていたG3集合(いわゆる3バイトEUC)にJIS X 0212を割り当てるという変更がなされています。

EUC-JP

IANA Character SetsではExtended_UNIX_Code_Packed_Format_for_JapaneseのAlias、つまり、日本語EUC(圧縮形式)のことです。⁠UNIX SYSTEM V リリース 4 日本語環境共通規約」の定義を参照しているように見えます。ここではG0はUS-ASCIIで、JIS X 0212を含みます。

ほぼ同じものがUI-OSF日本語環境実装規約 Version 1.1でも定義されています。

eucJP-ms

eucJP-msはTOG/JVC(オープン・グループ / 日本ベンダ協議会)CDE/Motif 技術検討 WGがUnicode とユーザー定義文字・ベンダ定義文字に関する問題点と解決策コード変換規則において、⁠Microsoft Windows 3.51 式の変換」として定めたエンコーディングです。

EUC-JPと文字集合としては同じですが、Unicodeとの変換において文字の対応が異なります。後述のCP51932の変換結果との調和を考えながら、Unix系のソフトウェアからEUCとして送信されてきたデータを変換する際に用います。

CP51932

Windows Codepage 51932は、MicrosoftのInternet Explorerで「日本語 (EUC)」を選択した際に用いられるエンコーディングです。このエンコーディングにはいわゆる3バイトEUCが存在しません。IEからEUCとして送信されたデータを変換する際にはこれを用いる必要があります。

ISO-2022-JP

元々1984年10月から始まったJUNETで用いられていた文字コードで、第27回プログラミング・シンポジウム(1986年1月)における和田英一によって当時用いられていたコードの誤りの指摘と、その後の小川貴英らとの議論を経て完成し、RFC 1468で定義されています。

なお、ステーフルなエンコーディングであるため、Ruby 1.9.1 においてはダミーエンコーディングという扱いになっています。

ISO-2022-JP

RFC1468で定義されています。これはいわゆる半角カナも、JIS X 0212も含みません。

CP50221

Windows Codepage 50221は、Outlook Express等でメールを出す際に用いられています。これはいわゆる半角カナを ESC ( I というエスケープシーケンスで含み、Windowsの機種依存文字も含んでいます。

ISO/IEC 8859

ISO/IEC 8859はヨーロッパで用いられたシングルバイトのエンコーディングで、1から16まで破棄された12を除き、15の部が存在します。なかでも西欧向けのISO-8859-1はlatin1とも呼ばれ、英語、ドイツ語、イタリア語等を表せることから広く普及しました。

ISO/IEC 646は重ね打ち等を用いた文字合成を前提とした文字コードでしたが、ISO/IEC 8859は合成済みの文字を採用する、情報処理用のコードとして生まれました。しかし、合成済み文字を用いるために8bitには収まらず、複数のパートに分断されることとなりました。

Unicode

Unicodeは全ての文字を1つのコード体系に収めるという野心的なプロジェクトで、情報交換や情報処理で用いられます。

当初は16bit(=約6万文字)にすべての文字を収める計画でしたが、Unicode 1.1リリース頃には16bitには収まりきらないことが明らかとなりました。そのため、当初からあったU+0000~U+FFFFの領域であるBMP(Basic Multilingual Plane, 基本多言語面)に加え、U+10000~U+10FFFFまでの領域(追加面, Supplementary Planes)を用いることができるように拡張され、約100万文字を表せるようになりました。

UTF-8

UTF-8は、Unicodeのコードポイント1つを、8bitの1バイトから4バイトで表すエンコーディング方式です。バイト構造が非常に洗練されており、最初の1バイトと2バイト目以降は別の領域を用いるようになっています。これにより、最初の1バイトでその文字が何バイトかわかるだけでなく、バイト列の途中から見ても文字の途中かをすぐに判別できます。さらに、シフトJISのように2バイト目が別の文字として解釈されえたり、EUC-JPにある文字検索の際に、ある文字の2バイト目と別の文字の1バイト目にマッチしてしまったりといった問題がありません。BOM(Byte Order Mark)を持たないUTF-8を特にUTF-8Nと言うこともあります。

UTF8-MAC

Mac OS Xで用いられる、アップルによって修正された Normalization Form D(分解済み)という形式のUTF-8です。Mac OS Xでファイル名を扱う際に、システムから戻ってくる文字列はこの形式になります。

Ruby 1.9.1では、nkfで--ic=UTF8-MACのように入力を指定すると、合成済みUTF-8に変換することができます。

UCS-2

Unicodeリリース当初、まだUTF-8もUTF-16もなかった時代に、Unicode表現するために用いられていた文字コードです。その名の通り、2オクテット(=16bit)で1文字を表す方式で、U+0000~U+FFFFまでを表すことができます。逆に言うと、U+10000以降は表すことができないので、今となっては古い方式です。

UTF-16

UTF-16は、Unicodeコードポイントを16bitのコードユニット1つまたは2つで表すエンコーディングです。前述のUCS-2をベースにサロゲートペアを用いて拡張し、U+10FFFFまでのUnicodeコードポイント空間全てを表すことができます。

UTF-16系のエンコーディングには、BOM(Byte Order Mark)でエンディアンを判別するUTF-16と、ビッグエンディアンのUTF-16BE、リトルエンディアンのUTF-16LEが存在します。

RubyではUTF-16BEとUTF-16LEに対応していますが、ASCII互換なエンコーディングではないため、扱いに制限があります。

UTF-32

UTF-32は、Unicodeを32bitで表すエンコーディングです。情報交換用としてはあまり用いられませんが、情報処理用としてはしばしば用いられます。

UTF-16同様、RubyはUTF-32BEとUTF-32LEのみを扱います。

まとめ

Ruby 1.9.1では様々なエンコーディングを扱うことができますが、文字列を正しく扱うには適切なエンコーディングを指定することが重要です。正しいエンコーディングをより早い段階でStringに与えることが、快適なRuby M17N生活につながるのです。

おすすめ記事

記事・ニュース一覧