バイトオーダーマーク(BOM )は、特殊なUnicode文字コードU+FEFF ZERO WIDTH NO-BREAK SPACEの特定の使用法であり、テキストストリームの先頭にマジックナンバーとして出現すると、テキストを読み取るプログラムにいくつかのことを知らせることができます。 [ 1 ]
BOMの使用は任意です。BOMが存在すると、ファイルの先頭に非ASCIIバイトを想定していないものの、テキストストリーム自体は処理できるソフトウェアによるUTF-8の使用が妨げられる場合があります。
Unicodeは、8ビット、16ビット、または32ビットの整数単位でエンコードできます。16ビットおよび32ビット表現の場合、任意のソースからテキストを受信するコンピュータは、整数がどのバイト順でエンコードされているかを知る必要があります。バイトが入れ替わると、BOMは非文字のUnicodeコードポイントになります。したがって、テキストにアクセスするプロセスは、テキストストリーム自体以外の契約やメタデータを必要とせずに、最初の数バイトを調べてエンディアンを判断できます。通常、受信側のコンピュータは必要に応じてバイトを自身のエンディアンにスワップするため、処理にBOMは不要になります。
BOMのバイトシーケンスはUnicodeエンコーディングごとに異なり(UTF-8やUTF-7などUnicode標準外のものも含む。下の表を参照)、他のエンコーディングで格納されたテキストストリームの先頭にこれらのシーケンスが現れる可能性は低い。そのため、エンコードされたBOMをテキストストリームの先頭に配置することで、テキストがUnicodeであることを示し、使用されているエンコーディング方式を識別できる。このBOMの使用方法は「Unicode署名」と呼ばれる。
BOMは、単純に現在のエンコーディングでエンコードされたUnicodeコードポイントU+FEFF ZERO WIDTH NO-BREAK SPACEです。バイト列で始まるテキストファイルは、そのファイルがビッグエンディアンのUTF-16でエンコードされていることを示唆しています。[ 2 ]FE FF
データ ストリームの途中に BOM が現れた場合は、 ZWNBSP (ゼロ幅ノーブレーク スペース)という名前を使用する必要があります。Unicode では、これは BOM ではなく、通常のコード ポイント (つまり、ワード ジョイナー) として解釈されるべきであるとされています。Unicode 3.2 以降、この使用法はU+2060 WORD JOINERに置き換えられ、非推奨となっています。[ 1 ]
このコードポイントのUnicode 1.0名もですBYTE ORDER MARK。[ 3 ]
BOMのUTF-8表現は(16進数)バイトシーケンスです。EF BB BF
Unicode 標準では、UTF-8での BOM の使用は許可されていますが、[ 4 ]必須でも推奨でもありません。 [ 5 ] UTF-8 は常に同じバイト順なので、[ 6 ] UTF-8 での BOM の唯一の用途は、テキスト ストリームが UTF-8 でエンコードされていること、またはオプションの BOM を含むストリームから UTF-8 に変換されたことを最初に示すことです。また、標準では、エンコード間のラウンドトリップで情報が失われないように、また、それに依存するコードが引き続き動作するように、BOM が存在する場合は削除することを推奨していません。[ 7 ] [ 8 ] IETFは、プロトコルが (a) 常に UTF-8 を使用するか、(b) 使用されているエンコードを示す別の方法がある場合、「署名として U+FEFF を使用することを禁止すべきである」と推奨しています。[ 9 ]この推奨事項に従わない例として、テキストが UTF-8 でなければならないことと、BOM も必要な IETF Syslogプロトコルがあります。[ 10 ]
BOMを使用しないことで、テキストは拡張ASCII用に設計されたソフトウェアとの下位互換性を維持できます。例えば、多くのプログラミング言語では、文字列リテラル内には非ASCIIバイトを使用できますが、ファイルの先頭には使用できません。
UTF-8 エンコーディングを検出するのに BOM は必要ありません。UTF -8 はスパース エンコーディングです。つまり、可能なバイトの組み合わせの大部分は有効な UTF-8 テキストになりません。バイナリ データや他のエンコーディングのテキストには、UTF-8 として無効なバイト シーケンスが含まれている可能性が高いため、そのような無効なシーケンスが存在する場合はファイルが UTF-8 ではないことを示し、無効なシーケンスがない場合はテキストがUTF -8 であることを強く示唆します。事実上唯一の例外は、ASCII 範囲のバイトのみを含むテキストです。これは非 ASCII 7 ビット エンコーディングである可能性がありますが、これは現代のデータでは考えにくく、その場合でも ASCII との違いはわずかです (たとえば、'\' を '¥' に変更するなど)。
Microsoft のコンパイラ[ 11 ]やインタプリタ、およびMicrosoft Windows上の多くのソフトウェア(Windows 10 ビルド 1903 [ 12 ]より前のメモ帳など) は、ヒューリスティックを使用するのではなく、BOM を必須のマジック ナンバーとして扱います。これらのツールは、テキストを UTF-8 として保存するときに BOM を追加し、BOM が存在するか、ファイルに ASCII のみが含まれていない限り、UTF-8 を解釈できません。Windows PowerShell (5.1 まで) は、UTF-8 XML ドキュメントを保存するときに BOM を追加します。ただし、PowerShell Core 6 では、一部のコマンドレットに utf8NoBOM というスイッチが追加され、ドキュメントを BOM なしで保存できるようになりました。Google Docsも、ドキュメントをダウンロード用のプレーン テキストファイルに変換するときに BOM を追加します。-Encoding
UTF-16では、U+FEFFファイルまたは文字ストリームの最初のバイトにBOM(バイトオーダーマーク)を配置して、ファイルまたはストリームのすべての16ビットコードユニットのエンディアン(バイト順序)を示すことができます。このストリームを誤ったエンディアンで読み取ろうとすると、バイトが入れ替わり、Unicodeで「非文字」として定義されU+FFFE、テキストに決して出現してはならない文字であるが、が出力されます。
FE FFFF FEIANAに登録されている文字セットであるUTF-16BEとUTF-16LEについては、これらの文字セットの名前によって既にバイト順序が決定されているため、バイト順序マークを使用すべきではありません。
Unicode 標準の適合条項 D98 (セクション 3.10) には、「UTF-16 エンコーディング スキームは、BOM で始まる場合と始まらない場合があります。ただし、BOM がなく、上位レベルのプロトコルがない場合、UTF-16 エンコーディング スキームのバイト順序はビッグ エンディアンです。」と記載されています。上位レベルのプロトコルが有効かどうかは解釈の余地があります。たとえば、ネイティブのバイト順序がリトルエンディアンであるコンピュータのローカル ファイルは、暗黙的に UTF-16LE としてエンコードされていると主張される可能性があります。したがって、ビッグ エンディアンの前提は広く無視されています。HTML5 で使用されているW3C / WHATWGエンコーディング標準では、「utf-16」または「utf-16le」とラベル付けされたコンテンツは、「展開されたコンテンツを処理するため」リトルエンディアンとして解釈されることが指定されています。[ 13 ]ただし、バイト順序マークが存在する場合は、その BOM が「他の何よりも権威がある」ものとして扱われます。[ 14 ]
BOMがなくても、テキストが十分に長ければ、テキストがUTF-16かどうか、またバイト順がどうなっているかを検出することはかなり確実です。基本ラテン文字ブロック(U+0001~U+007F)の文字は、最上位バイトがNULL(0x00)です。ラテン文字以外の文字でも、改行文字やスペース(このブロックに含まれます)は頻繁に使用されます。ファイル内の偶数オフセットでNULLバイトがはるかに多く出現する場合は、ビッグエンディアンのUTF-16である可能性が高く、奇数オフセットで多く出現する場合は、リトルエンディアンのUTF-16である可能性が高いです。
UTF-32でもBOMを使用することは可能ですが、このエンコーディングは送信にはほとんど使用されません。それ以外の場合は、UTF-16と同じルールが適用されます。
リトルエンディアンUTF-32のBOMは、リトルエンディアンUTF-16のBOMに続いてUTF-16のNULL文字が続くパターンと同じで、2つの異なるエンコーディングでBOMのパターンが同じになる珍しい例です。BOMを使用してエンコーディングを識別するプログラマは、UTF-32と、先頭にNULL文字が付いたUTF-16のどちらが可能性が高いかを判断する必要があります。UTF-32は、4バイトごとにNULLであるため、BOMがなくても簡単に検出できます。
この表は、さまざまなエンコーディングで BOM がバイト シーケンスとしてどのように表現されるか、また、各バイトをレガシー エンコーディング( C0 コントロールにはキャレット表記を使用したWindows-1252 ) として解釈するテキスト エディタでそれらのシーケンスがどのように表示されるかを示しています。
U+FEFF 、コードポイントが属するブロック表2-4。7つのUnicodeエンコーディング方式
-8ではBOMの使用は必須でも推奨もされていませんが、BOMを使用する他のエンコーディング形式からUTF-8データが変換される場合や、BOMがUTF-8の署名として使用される場合には、BOMの使用が見られることがあります。
しかし、C++ ソース コードは BOM なしの UTF-8 でエンコードされていたため (Linux ではこれが一般的です)、Visual C++ コンパイラはソース コードが Windows ANSI でエンコードされていると誤って想定しました。