Python读取文件时遇到\uFEFF开头是UTF-8或UTF-16文件带BOM的表现,用"encoding='utf-8-sig'"可自动剥离BOM;手动处理需以rb模式读取并比对字节头;chardet对BOM检测冗余。

Python读取文件时遇到\ufeff开头是怎么回事
这是UTF-8或UTF-16文件带BOM(Byte Order Mark)的典型表现。Python在用open()以utf-8编码读取时,不会自动跳过BOM,导致首字符变成\ufeff——它不是空格,也不是零宽空格\u200b,而是一个独立的Unicode字符。常见于Windows记事本保存的UTF-8文件。
用encoding="utf-8-sig"最省事地跳过BOM
Python内置编码utf-8-sig会在读取时自动剥离BOM,写入时**不添加**BOM,是处理该问题的首选方案:
f = open("file.txt", encoding="utf-8-sig")
content = f.read() # content开头不会再有\ufeff
f.close()- 适用于所有含UTF-8 BOM的文件(
\xef\xbb\xbf),也兼容无BOM文件 - 不能用于
utf-16类编码;若需处理UTF-16 BOM,应改用utf-16或utf-16-sig - 写入时不加BOM,如需保留BOM(极少见),得手动写入
\ufeff
手动检测并移除BOM需要分三步走
当必须用utf-8编码(比如配合某些库强制要求)、或需区分BOM类型时,得自己检测字节头:
- 先以
rb模式打开,读前3–4字节 - 比对BOM签名:
b'\xef\xbb\xbf'(UTF-8)、b'\xff\xfe'(UTF-16 LE)、b'\xfe\xff'(UTF-16 BE) - 跳过对应字节数再解码,例如:
with open("file.txt", "rb") as f: raw = f.read() if raw.startswith(b'\xef\xbb\xbf'): content = raw[3:].decode("utf-8") elif raw.startswith(b'\xff\xfe'): content = raw[2:].decode("utf-16-le") else: content = raw.decode("utf-8")
注意:直接对str做.lstrip("\ufeff")不可靠——它只删首字符,但BOM可能被误判为内容;且对UTF-16文件无效。
立即学习“Python免费学习笔记(深入)”;
用chardet识别BOM前先确认是否真需要它
chardet能推测编码,但对BOM检测是多余动作:BOM本身已是明确的编码提示。除非文件没BOM又乱码,才需chardet.detect()辅助判断。
真正容易被忽略的是混合场景:比如日志文件一部分由Windows程序生成(带BOM),一部分由Linux脚本追加(无BOM)。这种情况下,单靠utf-8-sig只能解决开头,后续行仍可能因编码混杂出错——得逐行检测或统一预处理。


















