Python读UTF-8-BOM文件时开头多出\ufeff,是因为标准utf-8不识别BOM(\xef\xbb\xbf),将其解码为Unicode字符\ufeff;而utf-8-sig编码能自动检测并剥离BOM,是最直接安全的解决方案。

Python用open()读UTF-8-BOM文件时,为什么开头多出\ufeff?
因为标准utf-8编码不识别BOM,BOM(\xef\xbb\xbf)会被当作普通字符解码成Unicode码点\ufeff,出现在字符串开头。这不是乱码,是真实读入的字节——只是你没告诉Python“这BOM该被忽略”。
为什么encoding='utf-8-sig'能解决?
utf-8-sig是Python内置的变体编码:读取时自动检测并剥离BOM,写入时默认在开头写入BOM(除非显式禁用)。它不是“带BOM的UTF-8”,而是“带BOM感知能力的UTF-8处理逻辑”。
- 读文件:
open('file.txt', encoding='utf-8-sig')→\ufeff不会出现在结果字符串里 - 写文件:
open('out.txt', 'w', encoding='utf-8-sig')→ 默认写入\xef\xbb\xbf开头 - 若不想写BOM,得加
newline=''并手动控制,或改用utf-8写入
不用utf-8-sig的替代方案有哪些?
有,但都绕弯子,还容易漏判:
- 先用
rb模式读,手动切掉前3字节(仅当确定是BOM且文件非空):data = f.read()[3:].decode('utf-8') - 用
codecs模块:codecs.open(path, encoding='utf-8-sig')——本质同open(),无优势 - 读完再
.lstrip('\ufeff')——危险!万一文本真包含\ufeff(如某些富文本标记),会被误删
所以,只要目标是“干净读取带BOM的UTF-8”,utf-8-sig就是最直接、最安全的选择。
立即学习“Python免费学习笔记(深入)”;
Windows记事本保存的“UTF-8”文件,为什么总带BOM?
因为旧版Windows记事本把“UTF-8”和“UTF-8 with BOM”混为一谈。它根本不会生成无BOM的UTF-8——选“UTF-8”保存,实际写的就是utf-8-sig格式。这也是为什么你在Windows上用utf-8读记事本文件时,第一行常莫名多一个空格或报错。
跨平台协作时,这个细节最容易被忽略:Linux/macOS工具(如vim、cat)通常不写BOM,而Python脚本若硬写utf-8去读Windows产出的文件,就会撞上\ufeff。


















