端序記號

端序記號，或稱位元組順序記號（英語：byte-order mark，BOM）是位於碼點U+FEFF的統一碼字符的名称。當以UTF-16或UTF-32來將UCS/統一碼字符所組成的字串編碼時，這個字符被用來標示其端序。它也被用來當做標示文件是以UTF-8、UTF-16或UTF-32編碼的記號。 端序記號通常有幾種涵義： 在16位元和32位元的情況下，文字流的端序。 表示文字流非常有可能是統一碼編碼。 使用的是哪一種統一碼字元編碼。 端序記號的使用是選擇性的。它的存在會干擾那些不希望檔案開頭出現非ASCII字元、但可以用其他方式處理文字流的軟體對於UTF-8的使用。 統一碼可以以8位元、16位元或32位元整數為單位進行編碼。對於16位元和32位元的表示方法，從任意來源接收文本的電腦需要知道整數是以何種端序編碼的。端序記號的編碼方式與文件檔案的其他部分相同，如果它的位元組被調換，就會變成一個非字元的統一碼碼位。因此，訪問文本的過程中，可以透過檢查這頭幾個位元組來確定端序，而不需要文字流本身以外的一些約定或元資料。一般來說，如果有必要，接收資料的電腦會將位元組換成自己的端序，不再需要端序記號進行處理。 每個統一碼編碼（包括統一碼標準以外的編碼，如UTF-7，見下表）的BOM位元組序列都不一樣，而且這些序列都不可能出現在以其他編碼儲存的文字流的開頭。因此，在文字流的開頭放置一個編碼的BOM，可以表明文本是統一碼，並識別所使用的編碼方案。這種對BOM字元的使用被稱為「統一碼簽名」。 字符U+FEFF如果出现在字节流的开头，则用来标识该字节流的字节序，是高位在前还是低位在前。如果它出现在字节流的中间，则表达零寬度非换行空格的意义，用户看起来就是一个空格。从Unicode3.2开始，U+FEFF只能出现在字节流的开头，只能用于标识端序，就如它的名称——端序記號——所表示的一样；除此以外的用法已被捨棄。取而代之的是，使用U+2060來表达零寬度無斷空白。 雖然在統一碼標準中，允許UTF-8也中使用端序記號，但實際上並不一定需要。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的環境中則會顯示ï»¿。 統一碼標準允許在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中，端序記號被放置為檔案或文字串流的第一個字符，以標示在此檔案或文字串流中，以所有十六位元為單位的字碼的端序。如果試圖用錯誤的端序來讀取這個流，位元組將被調換，從而產生字元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-16。 小端序UTF-32的BOM等同小端序UTF-16的BOM圖案後面加上一個NUL字元，這是一個不尋常的例子，即BOM在兩種不同的編碼中是相同的形式。使用BOM來識別編碼的程序員必須分辨文件是UTF-32編碼還是單純以NUL作為第一個字元。 左至右符號 右至左符號 FAQ - UTF-8, UTF-16, UTF-32 & BOM. Unicode.org. [2017-01-28]. （原始内容存档于2021-05-02）.  The Unicode® Standard Version 9.0 (PDF). The Unicode Consortium. [2021-06-16]. （原始内容存档 (PDF)于2021-05-07）.  The Unicode Standard 5.0, Chapter 2:General Structure (PDF): 36. [2009-03-29]. （原始内容存档 (PDF)于2021-04-22）. Table 2-4. The Seven Unicode Encoding Schemes  The Unicode Standard 5.0, Chapter 2:General Structure (PDF): 36. [2008-11-30]. （原始内容存档 (PDF)于2021-04-22）. Use of a BOM is neither required nor recommended for UTF-8, but may be encountered in contexts where UTF-8 data is converted from other encoding forms that use a BOM or where the BOM is used as a UTF-8 signature  FAQ - UTF-8, UTF-16, UTF-32 & BOM: Can a UTF-8 data stream contain the BOM character (in UTF-8 form)? If yes, then can I still assume the remaining UTF-8 bytes are in big-endian order?. [2008-03-29]. （原始内容存档于2012-09-01）.  Re: pre-HTML5 and the BOM from Asmus Freytag on 2012-07-13 (Unicode Mail List Archive). Unicode.org. [2012-07-14]. （原始内容存档于2019-06-16）.  Bug ID: JDK-6378911 UTF-8 decoder handling of byte-order mark has changed. Bugs.sun.com. [2017-01-28]. （原始内容存档于2017-12-19）.  Yergeau, Francois. UTF-8, a transformation format of ISO 10646. IETF. November 2003 [May 15, 2014]. RFC 3629.  Alf P. Steinbach. Unicode part 1: Windows console i/o approaches. 2011 [24 March 2012]. （原始内容存档于2012-03-22）. However, since the C++ source code was encoded as UTF-8 without BOM (as is usual in Linux), the Visual C++ compiler erroneously assumed that the source code was encoded as Windows ANSI.  UTF-16LE. Encoding Standard. WHATWG. [2021-06-17]. （原始内容存档于2015-02-04）.  Decode. Encoding Standard. WHATWG. [2021-06-17]. （原始内容存档于2015-02-04）.  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（页面存档备份，存于互联网档案馆）