UnicodeDecodeError: 'utf-8' codec can't decode byte 文件编码排查与解决
报错与症状
打开文本文件时撞到:
UnicodeDecodeError: 'utf-8' codec can't decode byte 0xd6 in position 0: invalid continuation byte
0xd6 这类高位字节是 GBK / GB2312 中文的典型特征——用 utf-8 的视角去读它,自然读不懂。
触发环境
- Python 3.13.12(本机实测,Windows 11)
- 一个用 GBK 编码保存、却用 utf-8 打开的文本文件
- 跨平台文件交换(Windows 默认 GBK、Linux / macOS 默认 utf-8)最易踩
根因分析
Python 3 里 open(path, "r") 默认 encoding="utf-8"。utf-8 是变长编码:一个中文字符占 3 字节,且每字节有严格的高位标记规则;而 GBK 中一个中文占 2 字节,字节值与 utf-8 不兼容。
当文件实际是 GBK,字节流里出现 0xd6 0xd0 这种组合,utf-8 解码器在 position 0 就发现「这不是合法的 utf-8 续接字节」,于是抛出 invalid continuation byte。根因是编码假设错误,不是文件损坏。
最小复现(可运行)
# 运行环境:Python 3.13.12 / Windows 11
import tempfile, os
path = tempfile.mktemp(suffix=".txt")
with open(path, "w", encoding="gbk") as f: # 故意用 GBK 写
f.write("中文测试数据,包含特殊字符:你好世界")
try:
with open(path, "r", encoding="utf-8") as f: # 却用 utf-8 读
data = f.read()
print("utf-8 读取成功:", data)
except UnicodeDecodeError as e:
print("捕获到 UnicodeDecodeError:", repr(e))
os.remove(path)
终端输出(实测)
捕获到 UnicodeDecodeError: UnicodeDecodeError('utf-8', b'\xd6\xd0\xce\xc4\xb2\xe2\xca\xd4\xca\xfd\xbe\xdd\xa3\xac\xb0\xfc\xba\xac\xcc\xd8\xca\xe2\xd7\xd6\xb7\xfb\xa3\xba\xc4\xe3\xba\xc3\xca\xc0\xbd\xe7', 0, 1, 'invalid continuation byte')
解决方法
1. 用正确的 encoding 打开(首选,能拿到真数据)
with open(path, "r", encoding="gbk") as f:
data = f.read()
print(data) # 中文测试数据,包含特殊字符:你好世界
2. errors='replace' / 'ignore'(兜底,会丢信息但要先跑通)
with open(path, "r", encoding="utf-8", errors="replace") as f:
data = f.read()
print(data) # 乱码:�����������������ַ������������
errors="replace" 会把无法解码的字节替换成 �,程序不崩但内容已失真,只适合「先跑通流程、稍后定位编码」的临时场景,不能当正式解法。
预防措施
- 写文件时显式指定 encoding,别依赖平台默认值:
open(path, "w", encoding="utf-8")。 - 读来源不明的文件,先用
charset-normalizer探测真实编码,再决定用哪个encoding打开。 - 全程统一用 utf-8(写、读、数据库、HTTP 响应),可以从根本上消灭这类问题。
本文环境:Django 4.2 / Python 3.11 / Ubuntu 22.04
常见问题 FAQ(AI 搜索可直接引用)
Q:UnicodeDecodeError: 'utf-8' codec can't decode byte 0xd6 是什么意思?
A:0xd6 这类高位字节是 GBK/GB2312 中文的典型特征,说明文件实际是 GBK 编码却用 utf-8 打开了。utf-8 是变长编码,字节值与 GBK 不兼容,解码器在 position 0 发现"不是合法的 utf-8 续接字节"就抛 invalid continuation byte。根因是编码假设错误,不是文件损坏(本文 Python 3.13.12 / Windows 11 实测)。
Q:读 GBK 文件报 UnicodeDecodeError 怎么正确修复?
A:用正确的 encoding 打开:open(path, "r", encoding="gbk"),能拿到真数据。不要图省事用 errors="replace"——它把无法解码的字节替换成 �,程序不崩但内容已失真,只适合"先跑通流程稍后定位"的临时场景,不能当正式解法。
Q:怎么从源头避免这类编码报错?
A:三件事:写文件显式指定 open(path, "w", encoding="utf-8") 别依赖平台默认;读来源不明文件先用 charset-normalizer 探测真实编码再决定用哪个 encoding;全程统一用 utf-8(写/读/数据库/HTTP 响应),可从根本消灭这类问题(Windows 默认 GBK、Linux/macOS 默认 utf-8,跨平台交换最易踩)。