UTF-8

UTF-8（ユーティーエフはち、ユーティーエフエイト）はISO/IEC 10646 (UCS) とUnicodeで使える8ビット符号単位（1–4バイトの可変長）の文字符号化形式および文字符号化スキーム。
正式名称は、ISO/IEC 10646では “UCS Transformation Format 8”、Unicodeでは “Unicode Transformation Format-8” という。両者はISO/IEC 10646とUnicodeのコード重複範囲で互換性がある。RFCにも仕様がある。
2バイト目以降に「/」などのASCII文字が現れないように工夫されていることから、UTF-FSS (File System Safe) ともいわれる。旧名称はUTF-2。
UTF-8は、データ交換方式・ファイル形式として一般的に使われる傾向にある。
当初は、ベル研究所においてPlan 9で用いるエンコードとして、ロブ・パイクによる設計指針のもと、ケン・トンプソンによって考案された。
エンコード体系.
ASCII文字と互換性を持たせるために、ASCIIと同じ部分は1バイト、その他の部分を2–6バイトで符号化する。4バイトのシーケンスでは21ビット (0x1FFFFF) まで表現することができるが、Unicodeの範囲外となる17面以降を表すもの（U+10FFFFより大きなもの）は受け付けない。
また、5–6バイトの表現は、ISO/IEC 10646による定義とIETFによるかつての定義で、Unicodeの範囲外を符号化するためにのみ使用するが、Unicodeによる定義とIETFによる最新の定義では、5–6バイトの表現は不正なシーケンスである。
後述のセキュリティの項に詳細はあるが、符号化は最少のバイト数で表現しなければならない。そのため、バイト数ごとにUnicodeの符号位置の最小値（下限）も設けている。
例えば、1バイトで表現するASCII文字は2バイト以上でも表現できるが、バイト数ごとの下限によってこれを回避している。
ビットパターンは以下のようになっている。
Unicodeの符号位置を2進表記したものを、上のビットパターンのx, yに右詰めに格納する（最少のバイト数で表現するため、yの部分には最低1回は1が出現する）。符号化されたバイト列は、バイト順に関わらず左から順に出力する。
1バイト目の先頭の連続するビット "1"（その後にビット "0" が1つ付く）の個数で、その文字のバイト数がわかるようになっている。また、2バイト目以降はビットパターン " で始まり、1バイト目と2バイト目以降では値の範囲が重ならないので、文字境界を確実に判定できる。すなわち、任意のバイトの先頭ビットが " の場合は1バイト文字、" の場合は2バイト以上の文字の2番目以降のバイト、" の場合は2バイト文字の先頭バイト、" の場合は3バイト文字の先頭バイト、" の場合は4バイト文字の先頭バイトであると判定できる。
7バイト以上の文字は規定されないため、codice_1, codice_2は使用されない。このため、バイト順マーク (BOM) にcodice_1とcodice_2を使用するUTF-16やUTF-32が、UTF-8と混同されることはない。
サロゲートペアの扱い.
UTF-16ではサロゲートペアで表されるような、基本多言語面外の符号位置をUTF-8で表す時は、変換元がUTF-16でサロゲートペアの時には codice_5–codice_6, codice_7–codice_8 を表すUTF-8にそのまま変換したりはせず、codice_9–codice_10 の符号位置にデコードしてから変換する。そのままUTF-8で符号化したような列は不正なUTF-8とされる。
サロゲートペアのままUTF-8と同等の符号化を行う符号化は、CESU-8 () として別途定義されている。実用に供されている例としては、Oracle Databaseのバージョン8以前において、UTF-8として3オクテットまでのオクテット列しか扱えなかったために定義されたものである。本来のUTF-8における4オクテット列の代わりに、サロゲート符号位置を表す3オクテット列のペア（上位が codice_11–codice_12、下位が codice_13–codice_14）で表現される。
現在のOracle Databaseでも、CESU-8を「UTF8」として、「普通のUTF-8」を「AL32UTF8」として扱っているため注意を要する。MySQLでも「utf8」を指定した場合は4オクテット列が扱えず、CESU-8相当の符号化を必要とする（4オクテット列対応のUTF-8は「utf8mb4」として別途定義されているが、MySQL 5.5.3以降でないと使用できない）。
また、Javaの一部の内部実装で用いられているModified UTF-8も、サロゲートペアをそのまま残す仕様となっている。ただし、NULL文字をcodice_15とエンコードする（これもUTF-8規格外）点で、CESU-8とも異なる実装となっている。
セキュリティ.
UTF-8のエンコード体系には冗長性があり、同じ文字を符号化するのに複数の表現が考えられる（例: スラッシュ記号である「/」を 0x2F という1バイトで表現するのではなく、0xC0 0xAF という2バイトもしくはそれより大きなバイト数で表現する）。かつてはそのような表現も許容されていたが、ディレクトリトラバーサルなどの対策として行われる文字列検査を冗長な表現によりすり抜ける手法が知られるようになったため、現在の仕様では最少のバイト数による表現以外は不正なUTF-8シーケンスとみなさなければならない。
ISO/IEC 10646の定義が5バイト以上の表現を許容していることにより、正しくない実装を行ったバグのあるシステムにおいてエンコード時にバッファオーバーフローが発生する可能性も指摘されている。
バイト順マークの使用.
UTF-8で符号されたテキストデータはエンディアンに関わらず同じ内容になるので、バイト順マーク (BOM) は必要ない。しかし、テキストデータがUTF-8で符号化されていることの標識として、データの先頭にEF BB BF（16進。UCSでのバイト順マークU+FEFFのUTF-8での表現）を付加することが許される。一部のテキスト処理アプリケーション（テキストエディタなど）がBOMを前提とした動作をすることがある。TeraPad、EmEditor、MIFESのようにBOMを付加するかどうかを選択できるものもある。
なお、日本の特殊事情として、このシーケンスがある方をUTF-8、ない方を特にUTF-8Nと呼ぶこともあるが、このような呼び分けは日本以外ではほとんど知られておらず、また公的規格などによる裏付けもない。
このシーケンスを通常の文字と認識するプログラムでは、先頭に余分なデータがあるとみなされて問題となることがある。例えば、Unix系OSにおける実行可能スクリプトは、ファイル先頭が「#!」から始まるとき、それに続く文字列をインタプリタのコマンドとして認識するが、多くのシステムでは、このシーケンスが存在するとこの機能が働かず実行できない。PHPでは、codice_16の前に出力されるため、codice_17関数の実行に失敗する原因となる。HLSLやGLSLのシェーダープログラムコンパイラ（fxcやglslangValidator）はBOMを処理できず、コンパイルエラーとなる。
逆にこのシーケンスがない場合、UTF-8と認識できないプログラムも存在する。たとえば、。Microsoft Visual C++は既定でBOMなしUTF-8を認識せず、システムロケール設定に応じたマルチバイトエンコーディングとみなすが、Visual C++ 2015以降ではコンパイルオプションを指定することでBOMなしUTF-8を認識することができるようになっている。
また、BOMがなくともエンコード自動推定によってUTF-8とShift_JISなどを区別することのできるプログラムもあるが、ASCII部以外の文字が少ない場合に誤認することが多い。
プロトコルが常にUTF-8であることを強制しているものである場合はこのシーケンスを禁止するべきで、この場合ファイル先頭にこのシーケンスが現れると “ZERO WIDTH NO-BREAK SPACE” と見なされる。逆にプロトコルがそれを保証しない場合このシーケンスは禁止されずファイル先頭のそれはバイト順マークと見なされる。
Windows 10のメモ帳アプリは、2019年の19H1アップデートからBOM無しUTF-8がデフォルトになった。