端序记号

端序记号，或称位元组顺序记号（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的文件。它只用来标示一个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**
在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 & BOMdate=20080926024051 -  The Unicode Standard, chapter 2.6  Encoding Schemesdate=20081116041027 -  The Unicode Standard, chapter 2.13  Special Characters and Noncharacters, section Byte Order Mark（BOM）date=20081116041027 -  The Unicode Standard, chapter 16.8 Specials, section Byte Order Mark (BOM): U+FEFFdate=20081116041050