首页/开发/正则与编码速查/UTF-16 字节序与 BOM 标记

UTF-16 字节序与 BOM 标记

UTF-16 用 2 或 4 字节表示一个码位,因此存在大端与小端两种字节序;BOM(U+FEFF)写在流首用来声明序别,FF FE 表示小端、FE FF 表示大端,缺了它解码器就可能把整段内容读成乱码。

正则与编码速查开发更新于 2026-10-17
​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌​​‌​‌‌‌‌​‌‌‌​​‌​​‌‌​​‌​‌​‌‌​​‌‌‌​‌‌​​‌​‌​‌‌‌‌​​​​​‌​‌‌‌‌​‌‌‌​‌​‌​‌‌‌​‌​​​‌‌​​‌‌​​​‌‌​​​‌​​‌‌​‌‌​​​‌​‌‌​‌​‌‌​​​‌​​‌‌​‌‌‌‌​‌‌​‌‌​‌​​‌​‌‌​‌​‌‌​​‌​‌​‌‌​‌‌‌​​‌‌​​‌​​​‌‌​‌​​‌​‌‌​​​​‌​‌‌​‌‌‌​​​‌​‌‌‌​​‌‌​‌​​​​‌‌‌​‌​​​‌‌​‌‌​‌​‌‌​‌‌​​

UTF-16 与字节序问题

UTF-16 把基本平面字符编成 2 字节,增补平面字符编成代理对共 4 字节。多字节单位带来字节序问题:同样的码位在小端机器上写作低字节在前,在大端机器上高字节在前,两者字节序列完全相反。UTF-16 的解决办法是在流首写一个 U+FEFF 作为字节序标记(BOM),解码器读到 FF FE 判为小端、FE FF 判为大端;外部已有声明(如 HTTP 头、XML 声明)时,BOM 只是冗余确认。

基本信息

编码单位2 字节基本单元,增补平面用 4 字节代理对
小端 BOMFF FE(Windows 记事本「Unicode」默认格式)
大端 BOMFE FF(网络字节序习惯,部分协议使用)
无 BOM 写法显式指定 UTF-16LE 或 UTF-16BE 才能安全解码
内存表示Java 与 .NET 的字符串内部使用 UTF-16;JavaScript 字符串是 UTF-16 码元序列
典型场景Windows 宽字符 API、Java/.NET 字符串、部分旧协议报文

典型使用场景

  • 读取 Windows 导出的文本:记事本另存为「Unicode」即 UTF-16LE 带 BOM
  • Java/.NET 程序与文件交互:字符串内部是 UTF-16,落盘时需明确指定编码与字节序
  • 对接旧协议或老硬件:报文按 UTF-16BE 定义并要求字节数对齐
  • 排查乱码:看到「字符之间夹着不可见字符」或成对反向字节,先怀疑字节序弄反
  • 跨语言数据交换:确认前后端与语言实现都是 UTF-8,避免 UTF-16 环节引入 BOM

识别与转换示例

识别与转换示例
xxd -l 16 sample.txt                 # 看开头是 ff fe(小端)还是 fe ff(大端)
file sample.txt                      # 输出 Little-endian UTF-16 with BOM 等提示
iconv -f UTF-16 -t UTF-8 sample.txt -o out.txt      # 有 BOM 时由 BOM 决定字节序
iconv -f UTF-16LE -t UTF-8 sample.txt -o out.txt    # 无 BOM 时必须显式指定序别
python -c "print(open('sample.txt', encoding='utf-16').read()[:20])"   # utf-16 会按 BOM 自动判定
python -c "b=open('sample.txt','rb').read(8); print(b)"                # 直接看原始字节,避免被自动判定掩盖问题

字节序与标识对照

场景常见字节序首两字节
Windows 文本文件(记事本 Unicode)小端FF FE
Windows 宽字符 API 内存布局小端不适用(内存中无标记)
Java / .NET 字符串内存UTF-16 码元序列不适用
XML/HTML 规范建议由 BOM 或声明决定FE FF 或 FF FE
网络协议习惯大端FE FF
同一份文件里 BOM 只能出现一次,且必须在最开头。文本合并时若把两个带 BOM 的文件拼起来,第二个 BOM 会变成正文里的零宽不换行空格(U+FEFF),表现为「看不见但比较失败」的诡异问题。
Web 与配置场景优先 UTF-8:JSON 规范要求 UTF-8,HTTP 与大多数服务端框架默认也是 UTF-8。在中间某环引入 UTF-16 与 BOM,会让下游解析器把 BOM 当内容读入(例如 JSON 首个字符不是花括号而报解析错误)。
编程语言里用 utf-16 与 utf-16le 语义不同:前者会读并消耗 BOM、写出时也补 BOM;后者把 BOM 当普通字符处理。省略 BOM 的文件用前者打开会得到一个不可见字符开头的字符串,这类问题在日志里最难定位。

易错点

  • 把 BOM 当正文第一个字符:字符串首出现不可见字符,导致与常量比较失败、JSON 解析报错 → 读取时剥离 BOM 或用感知 BOM 的方式打开
  • 小端内容按大端解:每个字符的字节被交换,出现完全不相关的字符或方框 → 确认 BOM 或用显式 utf-16le/be 解码重试
  • 用 utf-16 读取无 BOM 文件:解码器按平台默认序别猜测,换机器结果不同 → 明确指定位序,或统一改成 UTF-8 存储
  • 多个文件拼接后未去重 BOM:正文中间出现零宽字符,字符串比较与正则匹配随机失败 → 合并前剥离 BOM,写回时统一不加 BOM
  • 在 JSON/HTTP 正文里使用 UTF-16 带 BOM:下游按规范期望 UTF-8,解析失败 → 接口层统一 UTF-8 无 BOM

数据来源与参考

  • Unicode 官方:UTF-16 编码形式与字节序标记章节
  • RFC 2781:UTF-16, an encoding of ISO 10646
  • Microsoft 文档:Working with Unicode 与字节序说明

整理校对:其其网ICT文档中心 · 本页地址:docs.qiqicto.com/regex/utf16-bom-endian.html

​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌​​‌​‌‌‌‌​‌‌‌​​‌​​‌‌​​‌​‌​‌‌​​‌‌‌​‌‌​​‌​‌​‌‌‌‌​​​​​‌​‌‌‌‌​‌‌‌​‌​‌​‌‌‌​‌​​​‌‌​​‌‌​​​‌‌​​​‌​​‌‌​‌‌​​​‌​‌‌​‌​‌‌​​​‌​​‌‌​‌‌‌‌​‌‌​‌‌​‌​​‌​‌‌​‌​‌‌​​‌​‌​‌‌​‌‌‌​​‌‌​​‌​​​‌‌​‌​​‌​‌‌​​​​‌​‌‌​‌‌‌​​​‌​‌‌‌​​‌‌​‌​​​​‌‌‌​‌​​​‌‌​‌‌​‌​‌‌​‌‌​​