6. 字节序标记 (BOM)
定义
UCS 字符 U+FEFF "ZERO WIDTH NO-BREAK SPACE" 也非正式地称为 "BYTE ORDER MARK" (缩写为 "BOM"). 该字符可以在文本中作为真正的 "ZERO WIDTH NO-BREAK SPACE" 使用, 但 BOM 这个名称暗示了该字符的第二种可能用途: 在 UCS 字符流前置一个 U+FEFF 字符, 作为一种 "签名" (signature).
作为签名使用
这类序列化流的接收者随后可以把起始字符作为提示, 用于判断:
- 该流由 UCS 字符组成
- 涉及的是哪一种 UCS 编码
- 对于具有多八位组编码单元的编码, 可据此识别八位组的序列化顺序
UTF-8 与 BOM
UTF-8 使用单八位组编码单元, 因此上述最后一种功能没有用处, BOM 将始终表现为八位组序列 EF BB BF.
解释规则
位置很重要
必须理解, 出现在流起始位置以外任何位置的字符 U+FEFF 必须按零宽非断行空格 (zero-width non-breaking space) 的语义解释, 不得被解释为签名.
移除时的考虑
当 U+FEFF 被解释为签名时, Unicode 标准建议可以在处理文本前移除起始的 U+FEFF 字符. 在某些情况下, 这种移除是必要的 (例如连接两个字符串时, 否则结果字符串可能在连接点包含一个非预期的 "ZERO WIDTH NO-BREAK SPACE"), 但它也可能影响不同层上的外部过程 (例如数字签名或字符计数), 因为这些过程依赖流中所有字符都存在.
建议
因此推荐:
- 如果没有充分理由, 避免移除被解释为签名的起始 U+FEFF
- 在适当时 (例如用于显示), 忽略它而不是移除它
- 仅在确有必要时才移除它
歧义问题
位于流第一个位置的 U+FEFF 可以被解释为零宽非断行空格, 并不总是签名.
Unicode 3.2 新增字符
为了减小这种不确定性, Unicode 3.2 新增了字符 U+2060 "WORD JOINER", 除签名功能外, 它与 U+FEFF 具有完全相同的语义和用法, 并强烈建议只使用它来表达词连接语义.
未来的明确性
最终, 遵循这一建议将使人们几乎可以确定任何起始 U+FEFF 都是签名, 而不是有意使用的 "ZERO WIDTH NO-BREAK SPACE".
协议指南
与此同时, 遗憾的是这种不确定性仍然存在, 并可能影响 Internet 协议. 协议规范可以限制将 U+FEFF 用作签名, 以减少或消除这种不确定性可能产生的不良影响.
为了在此类限制的优点 (降低不确定性) 与缺点 (失去签名功能) 之间取得平衡, 区分以下几种情况是有用的:
情况 1: 强制使用 UTF-8
对于协议规定始终为 UTF-8 的文本协议元素, 协议应该禁止将 U+FEFF 用作签名, 因为签名功能在这些情况下完全没有用处.
情况 2: 可靠的识别机制
对于协议提供了字符编码识别机制的文本协议元素, 如果预期该协议的实现能够始终正确使用这些机制, 协议也应该禁止将 U+FEFF 用作签名.
当协议元素从创建到其 (正确标记的) 传输期间一直严格处于实现控制之下时, 就属于这种情况.
情况 3: 没有识别机制
对于协议未提供字符编码识别机制的文本协议元素, 在以下情况下, 协议不应该禁止将 U+FEFF 用作签名:
- 禁令无法执行, 或
- 预期该协议的实现无法始终正确使用这些机制
后两种情况很可能出现在较大的协议元素中, 例如 MIME 实体, 尤其是当协议实现会从以下来源取得这些实体时:
- 文件系统
- 没有载荷编码识别机制的协议 (例如 FTP)
- 其他不能保证正确识别字符编码的协议 (例如 HTTP)
实现指南
禁止时
当协议禁止在某个协议元素中将 U+FEFF 用作签名时, 该协议元素中的任何起始 U+FEFF 必须被解释为 "ZERO WIDTH NO-BREAK SPACE".
未禁止时
当协议并未禁止在某个协议元素中将 U+FEFF 用作签名时, 实现应该准备好:
- 处理该元素中的签名
- 适当作出反应: 必要时使用该签名识别字符编码
- 视情况移除或忽略该签名
相关链接
- 上一节: 5. 标准版本
- 返回 RFC 3629 首页
- 下一节: 7. 示例