UTF-16とは、Unicodeの文字符号化形式/文字符号化方式の一つである。
概要
UTF-16とは、Unicodeの文字符号化形式/文字符号化方式の一つで、基本的には1文字2バイトで表現し、一部をサロゲートペアを用いて4バイトで表現する。
Unicode 1.x時代
1991年にUnicode 1.0が登場した時には、世界中全ての文字を2バイトで表現してしまおうという野望があった。昔の文書で「文字コード: Unicode」と書かれているものがあったら、Unicode 1.0 の2バイト固定長符号化方式が単にUnicodeと呼ばれていた時の名残かも知れない。
当時、最大の障壁と思われていた漢字も日本語・中国語・韓国語の漢字を無理矢理統合してなお2万字ほどのスペースを残すことができ、ラテン文字26個しか知らない欧米人は「他にこんなに文字数の多い言語はないから大丈夫だよね」と思ってUnicode 1.0を公開してみたらさあ大変。様々な言語がUnicode収録に名乗りを上げ、さらに中国や日本などを中心とした漢字圏からの要求によりマイナー漢字が実は万単位で存在することが判明して、2バイトで表現可能な範囲(63,536文字)では収拾がつかなくなった。
文字コード名「Unicode」からUTF-16へ
そこで、1996年にUnicodeのバージョンが2.0になる時に2バイトで全ての文字を表現するのをあきらめることになったのだが、既にJavaやWindowsなど多くのシステムが2バイト固定長方式を前提に設計されてしまっており、いまさら変更は不可能な状態であった。
そこで考案されたのが、空いていた領域にサロゲートペア(代用対)を割り当てる苦肉の策(後述)で、これにより表現可能な文字数は一気に約17倍になった。2-4バイト可変長方式になってしまうが、この方法ならUnicode 1.0で作成された文書は、Unicode2.0で配置の変わったもの(ハングルなど)を除けばそのまま読み込ませることができ、Unicode 1.0と高い互換性を維持することができる。
一方で、2バイト固定長を諦めた際に他の方式としてUTF-8なども定義されるようになったので、文字コード「Unicode」の後継だからといって上記方式のみを「Unicode 2.0」と呼ぶわけにもいかなかった。新文字コード名「UTF-16」の誕生である。
まずUnicodeが存在して、それを符号化するためにUTF-16があるところ、UTF-16で使うためだけにUnicode側にサロゲートペア領域割当という仕様変更があったという点は興味深い。
サロゲートペア
詳細はサロゲートペアの記事に譲るが、先方の記事はかなり長いのでおよその仕組みを記す。
UTF-16はその名の通り16ビット=2バイト単位なのだが、そのうち、特定の上位6ビット( 110110と 110111)を持つものをサロゲートペアとして別に扱う。6ビットの値が中途半端なのは、先述の通りUnicode 1.0の割当で空いていた領域を使用したからである。
110110で始まる上位サロゲートと110111で始まる下位サロゲートは必ずペアとして扱われる。16ビットから上位6ビットを除いた10ビットがデータ部分であり、上位下位合わせて20ビット(約100万)になる。
ここで、20ビットをそのまま使用すると16ビット以下で表現できる部分は非サロゲートペア文字と重複してしまう。そこでUTF-16では、領域を無駄なく使うために、20ビットを4ビットと16ビットに分け、先頭の4ビットに1を足して使うことにした。17ビット以上の位の値が10進数(+16進数)表記で、0-15(0-F)から1-16(1-10)になった。もっとも、拡張した領域の半分以上は未使用のままだったりする。
これに17ビット以上の位の値が0である非サロゲートペア文字を加えて、65536のほぼ17倍(サロゲートペアを差し引く必要があるが)の表現が可能になった。Unicodeの表現には21ビットが必要だが、上限値がU+10FFFFとキリの悪い値になっているのはUnicodeの上限値をUTF-16の限界を元に定めているためである。
またUnicodeは16ビット(65536文字)を単位に「面」という単位で全体を管理しており、17ビット以上の位の値が0である非サロゲートペア文字の部分を第0面(基本多言語面: Basic Multilingual Plane)として、以降第1面〜第16面まで続く。
バイトオーダーマーク
UTF-16という文字符号化形式にはUTF-16とUTF-16BEとUTF-16LEという文字符号化方式がある。2バイトのうち上位バイトを先に書くのがビッグエンディアン、後に書くのがリトルエンディアン。
UTF-16BEとUTF-16LEはテキストを読み込む前に予め外部から方式の指定を受けているので、バイトオーダーマークは使用禁止である。
バイトオーダーマークとしてUnicodeテキストの先頭に挿入する文字は、U+FEFF: ZERO WIDTH NO-BREAK SPACE (ZWNBSP) で、改行禁止を表す零幅文字である。
UTF-16では、先頭の2バイトがFE FF の順に並べばビッグエンディアン、FF FEの順に並べばリトルエンディアン、何もない場合はビッグエンディアンと解釈される。
FF FEに文字割当があるとBOMか普通の文字かわからなくなるので、Unicodeの仕様には FF FE には文字を割り当てないことが明記されている。