削除された内容 追加された内容
Meniv (会話 | 投稿記録)
OKWaveとかが普通にソースになってるのでテンプレート貼り付け。自分もそういうソース(前の版のIBM技術者のエッセイ)を貼り付けた側の人間ですが…。
編集の要約なし
4行目:
}}
{{Table Unicode}}
'''UTF-8'''(ユーティーエフはち、ユーティーエフエイト)は[[ISO/IEC 10646]] (UCS) と[[Unicode]]で使える8ビット符号単位の[[文字符号化方式|文字符号化形式及び文字符号化スキーム]]。
 
正式名称は、ISO/IEC 10646では‘UCS “UCS Transformation Format 8’8”、Unicodeでは‘Unicode “Unicode Transformation Format-8’8” という。両者はISO/IEC 10646とUnicodeのコード重複範囲で互換性がある。[[Request for Comments|RFC]]にも仕様がある<ref>[http://tools.ietf.org/html/rfc3629 RFC 3629] UTF-8, a transformation format of ISO 10646</ref>。
 
2バイト目以降に「/」などの[[ASCII]]文字が現れないように工夫されていることから、'''UTF-FSS''' (File System Safe) ともいわれる。旧名称はUTF-2。
 
データ交換方式、ファイル形式としては、一般的にUTF-8が使われる傾向がある。[[Linux]]のように、[[オペレーティングシステム|OS]]の標準文字エンコードとして使用される例も増えている。
 
当初は、[[ベル研究所]]において [[Plan 9]]で用いるエンコードとして、[[ロブ・パイク]]による設計指針のもと、[[ケン・トンプソン]]によって考案された<ref>[http://tools.ietf.org/html/rfc3629#page-3 RFC 3629 Page-3]</ref><ref>[http://www.cl.cam.ac.uk/~mgk25/ucs/utf-8-history.txt Rob Pike's UTF-8 history]</ref>。
 
== エンコード体系 ==
[[ASCII]]文字と互換性を持たせるために、ASCIIと同じ部分は1バイト、その他の部分を2-6バイトで符号化する。4バイトのシーケンスでは21bit (0x1FFFFF) まで表現することができるが、Unicodeの範囲外となる17面以降を表すもの(U(U+10FFFFより大きなもの)は受け付けない。また5-6バイトの表現は、ISO/IEC 10646による定義<ref>[http://std.dkuug.dk/jtc1/sc2/wg2/ ISO/IEC 10646:2003] Information technology -- Universal Multiple-Octet Coded Character Set (UCS)</ref>と[[Internet Engineering Task Force|IETF]]によるかつての定義<ref>RFC 2279 UTF-8, a transformation format of ISO 10646</ref>で、Unicodeの範囲外を符号化するためにのみ使用するが、Unicodeによる定義<ref>[http://www.unicode.org/versions/Unicode5.2.0/ The Unicode Standard, Version 5.2]</ref>とIETFによる最新の定義<ref>RFC 3629 UTF-8, a transformation format of ISO 10646</ref>では、5-6バイトの表現は不正なシーケンスである。
 
ビットパターンは以下のようになっている。
{| class="wikitable" style="font-family: 'Courier New', monospace; white-space: nowrap;"
|-
! Unicode
! colspan="6" | '''ビット列'''
! colspan="6" | '''バイト列'''
!| '''有効ビット'''
|-
| U+0000 … U+007F
| style="text-align: right;" | 0xxx xxxx
| colspan="5" rowspan="3" |
|| 00-7F
| colspan="5" rowspan="3" |
| rowspan="3" | {{0}}7bit
|-
| (min) U+0000
| style="text-align: right;" | 000 0000
| style="text-align: center;" | 00
|-
| (max) U+007F
| style="text-align: right;" | 111 1111
| style="text-align: center;" | 7F
|-
| U+0080 … U+07FF
| style="text-align: right;" | 110yyy yx
| style="text-align: right;" | 10xx xxxx
| colspan="4" rowspan="3" |
|| C2-DF
|| 80-BF
| colspan="4" rowspan="3" |
| rowspan="3" | 11bit
|-
| (min) U+0080
| style="text-align: right;" | 000 10
| style="text-align: right;" | 00 0000
| style="text-align: center;" | C2
| style="text-align: center;" | 80
|-
| (max) U+07FF
| style="text-align: right;" | 111 11
| style="text-align: right;" | 11 1111
| style="text-align: center;" | DF
| style="text-align: center;" | BF
|-
| U+0800 … U+FFFF
| style="text-align: right;" | 1110yyyy
| style="text-align: right;" | 10yxxx xx
| style="text-align: right;" | 10xx xxxx
| colspan="3" rowspan="3" |
|| E0-EF
|| 80-BF
|| 80-BF
| colspan="3" rowspan="3" |
| rowspan="3" | 16bit
|-
| (min) U+0800
| style="text-align: right;" | 0000
| style="text-align: right;" | 1000 00
| style="text-align: right;" | 00 0000
| style="text-align: center;" | E0
| style="text-align: center;" | A0
| style="text-align: center;" | 80
|-
| (max) U+FFFF
| style="text-align: right;" | 1111
| style="text-align: right;" | 1111 11
| style="text-align: right;" | 11 1111
| style="text-align: center;" | EF
| style="text-align: center;" | BF
| style="text-align: center;" | BF
|-
| U+10000 … U+1FFFFF
| style="text-align: right;" | 11110y yy
| style="text-align: right;" | 10yy xxxx
| style="text-align: right;" | 10xxxx xx
| style="text-align: right;" | 10xx xxxx
| colspan="2" rowspan="3" |
|| F0-F7
|| 80-BF
|| 80-BF
|| 80-BF
| colspan="2" rowspan="3" |
| rowspan="3" | 21bit
|-
| (min) U+10000
| style="text-align: right;" | 0 00
| style="text-align: right;" | 01 0000
| style="text-align: right;" | 0000 00
| style="text-align: right;" | 00 0000
| style="text-align: center;" | F0
| style="text-align: center;" | 90
| style="text-align: center;" | 80
| style="text-align: center;" | 80
|-
| (max) U+1FFFFF
| style="text-align: right;" | 1 11
| style="text-align: right;" | 11 1111
| style="text-align: right;" | 1111 11
| style="text-align: right;" | 11 1111
| style="text-align: center;" | F7
| style="text-align: center;" | BF
| style="text-align: center;" | BF
| style="text-align: center;" | BF
|-
| U+200000 … U+3FFFFFF
| style="text-align: right;" | 111110yy
| style="text-align: right;" | 10yyyx xx
| style="text-align: right;" | 10xx xxxx
| style="text-align: right;" | 10xxxx xx
| style="text-align: right;" | 10xx xxxx
| rowspan="3" |
|| F8-FB
|| 80-BF
|| 80-BF
|| 80-BF
|| 80-BF
| rowspan="3" |
| rowspan="3" | 26bit
|-
| (min) U+200000
| style="text-align: right;" | 00
| style="text-align: right;" | 0010 00
| style="text-align: right;" | 00 0000
| style="text-align: right;" | 0000 00
| style="text-align: right;" | 00 0000
| style="text-align: center;" | F8
| style="text-align: center;" | 88
| style="text-align: center;" | 80
| style="text-align: center;" | 80
| style="text-align: center;" | 80
|-
| (max) U+3FFFFFF
| style="text-align: right;" | 11
| style="text-align: right;" | 1111 11
| style="text-align: right;" | 11 1111
| style="text-align: right;" | 1111 11
| style="text-align: right;" | 11 1111
| style="text-align: center;" | FB
| style="text-align: center;" | BF
| style="text-align: center;" | BF
| style="text-align: center;" | BF
| style="text-align: center;" | BF
|-
| U+4000000 … U+7FFFFFFF
| style="text-align: right;" | 1111110y
| style="text-align: right;" | 10yy yyxx
| style="text-align: right;" | 10xxxx xx
| style="text-align: right;" | 10xx xxxx
| style="text-align: right;" | 10xxxx xx
| style="text-align: right;" | 10xx xxxx
|| FC-FD
|| 80-BF
|| 80-BF
|| 80-BF
|| 80-BF
|| 80-BF
| rowspan="3" | 31bit
|-
| (min) U+4000000
| style="text-align: right;" | 0
| style="text-align: right;" | 00 0100
| style="text-align: right;" | 0000 00
| style="text-align: right;" | 00 0000
| style="text-align: right;" | 0000 00
| style="text-align: right;" | 00 0000
| style="text-align: center;" | FC
| style="text-align: center;" | 84
| style="text-align: center;" | 80
| style="text-align: center;" | 80
| style="text-align: center;" | 80
| style="text-align: center;" | 80
|-
| (max) U+7FFFFFFF
| style="text-align: right;" | 1
| style="text-align: right;" | 11 1111
| style="text-align: right;" | 1111 11
| style="text-align: right;" | 11 1111
| style="text-align: right;" | 1111 11
| style="text-align: right;" | 11 1111
| style="text-align: center;" | FD
| style="text-align: center;" | BF
| style="text-align: center;" | BF
| style="text-align: center;" | BF
| style="text-align: center;" | BF
| style="text-align: center;" | BF
|}
 
Unicodeの符号位置を2進表記したものを、上のビットパターンのx, yに右詰めに格納する。最短のバイト数で符号化するため、yの部分には最低1回は1が出現する。符号化されたバイト列は、[[エンディアン|バイト順]]に関わらず左から順に出力する。これにより4バイトで21bit、6バイトで31bitまで表現することができる。
 
1バイト目の先頭の連続するビット "1" (その後にビット "0" が1つ付く)の個数で、その文字のバイト数が判るようになっている。また、2バイト目以降はビットパターン "10" で始まり、1バイト目と2バイト目以降では値の範囲が重ならないので、文字境界を確実に判定できる。すなわち、任意のバイトの先頭ビットが "0" なら1バイト文字、"10" なら2バイト以上の文字の2番目以降のバイト、"110" なら2バイト文字の先頭バイト、"1110" なら3バイト文字の先頭バイト、"11110" なら4バイト文字の先頭バイトであると判定できる。
 
7バイト以上の文字は規定されないため、0xFE、0xFFは使用されない。このため、[[バイトオーダーマーク|バイト順マーク]] (BOM) に0xFEと0xFFを使用するUTF-16やUTF-32が、UTF-8と混同されることはない。
 
== 特徴 ==
=== メリット ===
* バイトストリーム中の任意の位置から、その文字、前の文字、あるいは次の文字の先頭バイトを容易に判定することができる。
* 文字列の検索を単なるバイト列の検索として行っても、文字境界と異なる個所でマッチしてしまうことがない。たとえば[[Shift_JIS]]で「¥」(0x5C) を検索すると「表」(0x95 0x5C) の2バイト目にマッチしたり、[[EUC-JP]]で「海」(0xB3 0xA4) を検索すると「ここ」(0xA4 0xB3 0xA4 0xB3) にマッチしたりするのと同様のことが起きない。このため、[[マルチバイト文字]]を意識せず、[[ISO/IEC 8859-1|ISO 8859-1]]などの8bit文字向けに作られた膨大なプログラム資産を、比較的少ない修正で再利用できる。
** ただし、他のUnicodeの符号化と同様に、単にバイト列の比較では文字列が同一か判断できない場合がある。詳細は、[[Unicodeの等価性]]及び[[Unicode正規化|正規化]]を参照のこと。
* [[UTF-16]]や[[UTF-32]]と異なり、バイト単位の入出力を行うため、[[エンディアン|バイト順]]の影響がない。
* 31bitまで表現できるため、[[サロゲートペア]]を使用する必要がない。
* ASCII文字が主体の文書であれば、ほとんどデータサイズを増やさずにUnicodeのメリットを享受できる。UTF-16やUTF-32では、データサイズはほぼ2倍、4倍となる。
* 複数のUTF-8文字列を、単なる符号なし8ビット整数の配列とみなして辞書順ソートした結果は、Unicodeの符号位置の辞書順のソート結果(すなわちUTF-32に変換した後にソートした結果)と等しくなる。これに対して、サロゲートペアを含むUTF-16文字列を符号なし16ビット整数の配列とみなしてソートした結果は、Unicodeの符号位置の辞書順のソート結果と異なりうる。
 
=== デメリット ===
* UTF-8による符号化では、[[漢字]]や[[仮名 (文字)|仮名]]などの表現に3[[バイト (情報)|バイト]]を要する。このように、東アジアの従来文字コードでは[[マルチバイト文字|マルチバイト符号]]を用いて1文字2バイトで表現されていたデータが、1.5倍かそれ以上のサイズとなる。同様に、[[ISO/IEC 8859-1]]では1バイトで表現できた非ASCIIのラテン文字 ([[ウムラウト]]付きの文字など) も2バイトとなるし、その他の[[ISO/IEC 8859|ISO/IEC 8859シリーズ]]に属する文字符号ではデータ量がさらに増大しうる。
** なお、1バイトが9ビットである処理系では、この問題をあまり発生させずに符号化できるはずである。このアイディアに基づいた[[ジョークRFC]]がRFC 4042 “UTF-9” として[[2005年]]の[[エイプリルフール]]([[4月1日]])に公開された。
* 文字数とデータサイズが比例しないため、文字数を調べるには先頭から全データを読み取る必要がある。ただし、Unicodeでは一部の文字を合成によって表現することもできるから(例:「ぱ」は、U+3071のほかにもU+306F U+309Aでも表現できる)、Unicodeを採用する場合、文字列の文字数をその文字列のバイト数から計算できないことは、UTF-8に限ったことではない。
* 最短ではない符号やサロゲートペアなど、UTF-8の規格外だがチェックを行わないプログラムでは一見正常に扱われるバイト列が存在する。これらのバイト列を入力として受け入れてしまうと、プログラムが予期しない範囲のデータを生成するため、セキュリティ上の脅威となりうる<ref>RFC 3629, pp.9f.</ref>。
 
== サロゲートペアの扱い ==
[[UTF-16]]では[[Unicode#サロゲートペア|サロゲートペア]]で表されるような、[[基本多言語面]]外の符号位置をUTF-8で表す時は、変換元がUTF-16でサロゲートペアの時には U+D800 ~ U+DBFF, U+DC00 ~ U+DFFF を表すUTF-8にそのまま変換したりはせず、U+10000 ~ U+10FFFF の符号位置にデコードしてから変換する。そのままUTF-8で符号化したような列は不正なUTF-8とされる。
 
サロゲートペアのままUTF-8と同等の符号化を行う符号化は、'''CESU-8''' (Compatibility Encoding Scheme for UTF-16: 8-Bit) として別途定義されている。実用に供されている例としては、[[Oracle Database]]のバージョン8以前において、UTF-8として3オクテットまでのオクテット列しか扱えなかったために定義されたものである。本来のUTF-8における4オクテット列の代わりに、サロゲート符号位置を表す3オクテット列のペア(上位が ED A0 80 ~ ED AF BF、下位が ED B0 80 ~ ED BF BF)で表現される(現在のOracle Databaseでも、CESU-8を「UTF8」として、「普通のUTF-8」を「AL32UTF8」として扱っているため注意を要する)。
 
また、[[Java]]の一部の内部実装で用いられている'''Modified UTF-8'''も、サロゲートペアをそのまま残す仕様となっている。ただし、NULL文字を<code>C0 80</code>とエンコードする(これもUTF-8規格外)点で、CESU-8とも異なる実装となっている。
 
== セキュリティ ==
UTF-8のエンコード体系には[[冗長性 (情報理論)|冗長性]]があり、同じ文字を符号化するのに複数の表現が考えられる(例: スラッシュ記号である「/」を 0x2F という 1 バイトで表現するのではなく、0xC0 0xAF という 2 バイトもしくはそれより大きなバイト数で表現する)。かつてはそのような表現も許容されていたが、[[ディレクトリトラバーサル]]などの対策として行われる文字列検査を冗長な表現によりすり抜ける手法が知られるようになったため、現在の仕様では最も短いバイト数による表現以外は不正なUTF-8シーケンスとみなさなければならない<ref>Windowsにおける有名な[[ワーム (コンピュータ)|ワーム]]である[[Nimda|Nimdaウイルス]]は、[[Internet Information Services|IIS]]におけるUTF-8の脆弱性をもちいたものである。[http://gihyo.jp/admin/serial/01/charcode/0004 本当は怖い文字コードの話 第4回 UTF-8の冗長なエンコード]</ref>
 
ISO/IEC 10646の定義が5バイト以上の表現を許容していることにより、正しくない実装を行った[[バグ]]のあるシステムにおいてエンコード時に[[バッファオーバーフロー]]が発生する可能性も指摘されている。
 
== 文字種 ==
{| class="wikitable"
! B !! Unicode !! スクリプト !! [[JIS X 0201]] !! [[JIS X 0208]] !! [[JIS X 0212]] !! [[JIS X 0213]]
256行目:
なお、日本の特殊事情として、このシーケンスがある方を'''UTF-8'''、ない方を特に'''UTF-8N'''と呼ぶこともある<ref>{{Cite web |url=http://www-128.ibm.com/developerworks/library/utfencodingforms/index.html |archiveurl=http://web.archive.org/web/20050506211548/http://www-128.ibm.com/developerworks/library/utfencodingforms/index.html| accessdate=18 September 2013 |title=http://www-128.ibm.com/developerworks/library/utfencodingforms/index.html| archivedate=6 May 2005 |language=英語 |author=Mark Davis |publisher=[[IBM]] |title=Forms of Unicode}}</ref>が、このような呼び分けは日本以外ではほとんど知られておらず、また公的規格などによる裏付けもない<ref>このため、UTF-8という呼び名を使っていれば情報交換の相手が文書先頭にこのシーケンスがあると見なすと期待すべきではないし、また、UTF-8Nという呼び名は情報交換の際に用いるべきではない。</ref>。
 
このシーケンスを通常の文字と認識するプログラムでは、先頭に余分なデータがあるとみなされて問題となることがある。例えば、[[Unix系]]OSにおける実行可能[[スクリプト言語|スクリプト]]は、ファイル先頭が「[[シバン_ (Unix)|#!]]」から始まるとき、それに続く文字列を[[インタプリタ]]のコマンドとして認識するが、多くのシステムでは、このシーケンスが存在するとこの機能が働かず実行できない。
 
逆にこのシーケンスがないとUTF-8と認識できないプログラムも存在する。とくにASCII部以外の文字が少ない場合に誤認することが多い (たとえば、[[Microsoft Excel]]では、[[Comma-Separated Values|CSVファイル]]を開くとき、このシーケンスが付加されていないUTF-8の場合は正常に読み込むことができない<ref>[http://okwave.jp/qa/q5574877.html ExcelでUTF-8の csvデータを表示するには]や[http://mism.blog13.fc2.com/blog-entry-202.html UTF-8で文字化け回避してCSV出力する方法]を参照</ref>。[[Microsoft Windows]]に付属する[[メモ帳]]、[[ワードパッド]]も同様。)
 
プロトコルが常にUTF-8である事を強制しているものである場合はこのシーケンスを禁止するべきで、この場合ファイル先頭にこのシーケンスが現れると “ZERO WIDTH NO-BREAK SPACE” と見なされる。逆にプロトコルがそれを保証しない場合このシーケンスは禁止されずファイル先頭のそれはバイト順マークと見なされる<ref>RFC 3629 [http://tools.ietf.org/html/rfc3629#section-6 6. Byte order mark (BOM)]</ref>。
 
== Unicode正規化との関係 ==
277行目:
}}</ref>。この改変されたNFDで正規化されるUTF-8を、Mac OS Xに付属する[[iconv]]などでは「UTF-8-MAC」として、[[Emacs]]ではUTF-8-HFSとして扱うことができる。
 
Mac OS Xのシステムコールでは、ファイルにアクセスする際、通常のUTF-8で指定しても内部で前述の正規化が行われるため、ユーザーやプログラマはこれを意識する必要はない。しかし、ファイルの一覧などを取得した場合、取得されるファイル名は正規化されたものとなる。このファイル名をそのまま他のUTF-8を使用する (しかし、NFDによる分解を前提としていない) システムにコピーすると、そのシステムの一般的な方法ではアクセスできないファイルが作成されてしまうおそれがある。
 
== 脚注 ==
285行目:
用語の日本語表記は原則として次にならった。{{cite web | url = http://www.unicode.org/terminology/term_en_ja.html | title = Unicode Terminology English - Japanese | publisher = Unicode, Inc | accessdate = 2010-01-01}}
 
== 関連項目 ==
*[[文字コード]]