要解决的问题
编码决定字符如何变成字节,换行决定行之间使用哪些字符,BOM 则是某些文件可能携带的前缀。三者相关但不是同一件事。先分清问题发生在哪一层,再决定采用重新读取、另存编码还是统一换行。
适用环境
Python 3.12;以下字节只在内存中构造,不读取或改写你的文本文件。
操作步骤与示例
先运行下面的小样本,再把输入替换为自己的资料;保留原始文件副本。
plain = "中文\n".encode("utf-8")
with_bom = b"\xef\xbb\xbf" + plain
assert with_bom.decode("utf-8-sig") == "中文\n"
assert "A\nB".encode("utf-8") != "A\r\nB".encode("utf-8")
print(plain.hex())
print(with_bom[:3].hex())如何判断结果
第一行输出中文和 LF 的 UTF-8 十六进制字节,第二行应为 efbbbf。LF 的字节是 0a,CRLF 是 0d0a;两个文本看起来接近,但字节和摘要并不相同。UTF-8 既可以没有 BOM,也可能被特定流程要求带 BOM。
常见问题与排查
不要把“去掉前三个字节”当作通用修复步骤:只有确认前缀确实为对应 BOM 才能处理。乱码也可能是早先错误解码并保存造成的;盲目再次转换可能使恢复更困难。
适用边界
示例没有自动推断任意文件编码。处理真实资料时先保留原始字节副本,按来源约定读取,再核对内容和接收端要求。扩展名只能提示用途,不能可靠证明字符编码。