字节序掩码

**位元組順序記號**（英語：byte-order mark，**BOM**）是位於碼點 `U+FEFF` 的統一碼字元的名稱。當以 UTF-16 或 UTF-32 來將 UCS / 統一碼字元所組成的字串編碼時，這個字元被用來標示其位元組序。它常被用來當做標示檔案是以 UTF-8、UTF-16 或 UTF-32 編碼的記號。

位元組順序記號通常有幾種涵義：

1. 在 16 位元和 32 位元的情況下，文字流的位元組順序。
2. 表示文字流非常有可能是 Unicode 編碼。
3. 使用的是哪一種 Unicode 字元編碼。

位元組順序記號的使用是選擇性的。它的存在會干擾那些不希望檔案開頭出現非 ASCII 字元、但可以用其他方式處理文字流的軟體對於 UTF-8 的使用。

Unicode 可以以 8 位元、16 位元或 32 位元整數為單位進行編碼。對於 16 位元和 32 位元的表示方法，從任意來源接收文字的電腦需要知道整數是以何種位元組順序編碼的。位元組順序記號的編碼方式與文件檔案的其他部分相同，如果它的位元組被調換，就會變成一個非字元的 Unicode 碼位。因此，存取文字的過程中，可以透過檢查這頭幾個位元組來確定位元組順序，而不需要文字流本身以外的一些約定或元資料。一般來說，如果有必要，接收資料的電腦會將位元組換成自己的位元組順序，不再需要位元組順序記號進行處理。

每個 Unicode 編碼（包括 Unicode 標準以外的編碼，如 UTF-7，見下表）的 BOM 位元組序列都不一樣，而且這些序列都不可能出現在以其他編碼儲存的文字流的開頭。因此，在文字流的開頭放置一個編碼的 BOM，可以表明文字是 Unicode，並識別所使用的編碼方案。這種對 BOM 字元的使用被稱為「Unicode 簽名」。

## 使用

字元 U+FEFF 如果出現在位元組流的開頭，則用來標識該位元組流的位元組序，是高位在前還是低位在前。如果它出現在位元組流的中間，則表達**零寬度非換行空格**的意義，使用者看起來就是一個空格。從 Unicode3.2 開始，`U+FEFF` 只能出現在位元組流的開頭，只能用於標識位元組序，就如它的名稱 —— 位元組順序記號 —— 所表示的一樣；除此以外的用法已被捨棄。取而代之的是，使用 `U+2060` 來表達零寬度無斷空白。

### UTF-8

在 UTF-8 中，雖然在 Unicode 標準上允許位元組順序記號的存在，但實際上並不一定需要。UTF-8 編碼過的位元組順序記號則被用來標示它是 UTF-8 的檔案。它只用來標示一個 UTF-8 的檔案，而不用來說明位元組順序。但同時，該標準也不建議在有位元組順序記號的情況下將其刪除，以便在不同的編碼之間轉換時不會丟失資訊，並讓依賴位元組順序記號的程式能順利運作。IETF 建議，如果一個協定 (a) 總是使用 UTF-8，或者 (b) 有一些其他方法來表明正在使用的編碼，那麼它「應該禁止使用 U+FEFF 作為簽名」。
許多視窗程式（包含記事本）會需要添加位元組順序記號到 UTF-8 檔案，否則將無法正確解析編碼，而出現亂碼。然而，在類 Unix 系統（大量使用文字檔案，用於檔案格式，用於行程間通訊）中，這種做法則不被建議採用。因為它會妨礙到如解譯器指令碼開頭的 Shebang 等的一些重要的碼的正確處理。它亦會影響到無法識別它的程式語言。如 gcc 會報告原始碼檔開頭有無法識別的字元。而在 PHP 中，如果沒有啟用輸出緩衝（output buffering），它會使得頁面內容開始被送往瀏覽器（即：使用者標頭檔已被送出），這使 PHP 指令碼無法指定使用者標頭檔（HTTP Header）。位元組順序記號在 UTF-8 中被表示為序列 `0xEF 0xBB 0xBF`，對大部分未準備好處理 UTF-8 的文字編輯器及網頁瀏覽器而言，在 ISO-8859-1 的環境中則會顯示 `ï»¿`。

Unicode 標準允許在 UTF-8 中使用 BOM，但並不要求或推薦使用它。位元組順序在 UTF-8 中沒有任何意義，所以它在 UTF-8 中的唯一用途是在開始時發出訊號，表明文字流是用 UTF-8 編碼的，或者表明它是從包含可選 BOM 的文字流轉換到 UTF-8 的。該標準也不建議在有 BOM 的情況下將其刪除，以便在不同的編碼之間往返不會丟失資訊，並使依賴 BOM 的代碼繼續工作。 IETF 建議，如果一個協定要麼 (a) 總是使用 UTF-8，要麼 (b) 有一些其他方法來表明正在使用的編碼，那麼它 "應該禁止使用 U+FEFF 作為簽名"。

UTF-8 是一種稀疏的編碼，意思是很大一部分可能的字元組合不會產生有效的 UTF-8 文字。任何其他編碼的二進制資料和文字都可能包含 UTF-8 無效的字元序列，唯一的例外是當文字純粹由 ASCII 範圍的字元組成的時候。因為所有的現代編碼都使用 ASCII 範圍的位元組來表示 ASCII 字元，所以無論發出這些位元組的系統打算使用什麼編碼，純 ASCII 的文字都可以被安全地解釋為 UTF-8。由於這些考慮，使用啟發式的分析方法可以很有把握地檢測出檔案是否使用 UTF-8，而不需要加入 BOM。
另一方面，微軟的編譯器和解釋器，以及許多 Microsoft Windows 上的軟體，如記事本，都將 BOM 視為一個必要的神奇數字，而不是使用啟發式分析法。這些工具在將文字儲存為 UTF-8 時添加了 BOM，並且只有在 BOM 存在或是檔案只包含 ASCII 字元時才能解釋 UTF-8。Windows PowerShell（截至 5.1 版本）在儲存 UTF-8 的 XML 檔案檔時，會添加一個 BOM。然而，PowerShell Core 6 在一些 cmdlets 上增加了一個 - Encoding 開關，稱為「utf8NoBOM」，這樣就可以在沒有 BOM 的情況下儲存檔案檔。Google 文件在將檔案檔轉換為純文字檔案以供下載時也會添加 BOM。

### UTF-16

在 UTF-16 中，位元組順序記號被放置為檔案或文字串流的第一個字元，以標示在此檔案或文字串流中，以所有十六位元為單位的字碼的端序（位元組順序）。如果試圖用錯誤的位元組順序來讀取這個流，位元組將被調換，從而產生字元 `U+FFFE`，這個字元被 Unicode 定義為「非字元」，不應該出現在文字中。例如，值為 `U+FFFE` 的碼位被保證將不會被指定成一個統一碼字元。這意味著 `0xFF`、`0xFE` 將只能被解釋成小端序中的 `U+FEFF`（因為不可能是大端序中的 `U+FFFE`）。

* 如果十六位元單位被表示成大端序，這位元組順序記號字元在序列中將呈現 `0xFE`，其後跟著 `0xFF`（其中的 `0x` 用來標示十六進位）。
* 如果十六位元單位使用小端序，這個位元組序列為 `0xFF`，其後接著 `0xFE`。

這兩個序列都不是有效的 UTF-8，所以它們的出現表明該檔案不是用 UTF-8 編碼的。

對於網際網路號碼分配局註冊的字元集 UTF-16BE 和 UTF-16LE，不應該使用位元組順序記號標記，因為這些字元集的名稱已經決定了位元組順序。如果在這樣的文字串流中的任何地方遇到 `U+FEFF`，將被解釋為一個「零寬度無斷點空間」。

如果沒有位元組順序記號，可以透過搜尋 ASCII 字元（即與 0x20-0x7E 範圍內的位元組相鄰的 0 位元組，還有 CR 和 LF 的 0x0A 和 0x0D）來猜測該文字是否為 UTF-16 及其位元組順序。大量的（即遠遠高於隨機）相同的順序是 UTF-16 的一個非常好的指示，而 0 是在偶數還是奇數位元組中表明了位元組的順序。然而，這依然可能會導致假陽性和假陰性。

Unicode 標準的一致性條款 D98（第 3.10 節）規定：「UTF-16 編碼方案可以以 BOM 開始，也可以不以 BOM 開始。然而，當沒有 BOM 時，在沒有高層協定的情況下，UTF-16 編碼方案的位元組順序是大端序。」是否有更高層次的協定是可以解釋的。例如，在一台本地位元組順序為小端序的電腦上的檔案，可能被默認為是以 UTF-16LE 編碼。因此，大端序的推定被廣泛地忽略了。在 HTML5 中使用的 W3C/WHATWG 編碼標準規定，標記為「utf-16」或「utf-16le」的內容將被解釋為小端序，「以處理部署的內容」。然而，如果出現了位元組順序記號，那麼該記號將被視為「比其他任何東西都更有權威性」。

將 UTF-16 解釋為基於位元組的編碼的程式可能會顯示出亂七八糟的字元，但是 ASCII 字元會被識別出來，因為 UTF-16 表示的低字元與 ASCII 代碼相同，因此會顯示相同的字元。0 的上字元可以顯示為無、空白、句號，或其他一些不變的字形。

### UTF-32

雖然位元組順序記號亦可以用於 UTF-32，但這個編碼很少用於傳輸，其規則如同 UTF-16。

小端序 UTF-32 的 BOM 等同小端序 UTF-16 的 BOM 圖案後面加上一個 NUL 字元，這是一個不尋常的例子，即 BOM 在兩種不同的編碼中是相同的形式。使用 BOM 來識別編碼的程式員必須分辨檔案是 UTF-32 編碼還是單純以 NUL 作為第一個字元。

## 不同編碼的位元組順序記號的表示

## 另見

* 左至右符號
* 右至左符號

## 參考文獻

## 外部連結

* Unicode FAQ: _UTF-8, UTF-16, UTF-32 & BOM_（頁面存檔備份，存於網際網路檔案館）
* The Unicode Standard, chapter 2.6 _Encoding Schemes_（頁面存檔備份，存於網際網路檔案館）
* The Unicode Standard, chapter 2.13 _Special Characters and Noncharacters_, section _Byte Order Mark（BOM）_ （頁面存檔備份，存於網際網路檔案館）
* The Unicode Standard, chapter 16.8 _Specials_, section _Byte Order Mark (BOM): U+FEFF_（頁面存檔備份，存於網際網路檔案館）