GBK 文件不再被改花:Claude Code 拒绝编辑非 UTF-8 文件
国内不少老项目里还躺着 GBK 编码的文件:早年的 Java / C# 工程、Windows 上导出的配置、某些 .bat 和 .ini。让 Claude Code 去改这种文件,过去可能出现一个很糟的结果:它只想改一行,保存后整份文件里的中文都坏了。
CLI 2.1.296 修掉了这个问题:
Edit 和 NotebookEdit 在不是合法 UTF-8 的文件(Windows-1252、Shift-JIS、GBK 等)里,会把每一个非 ASCII 字符都替换掉——这个问题已修复,这类编辑现在会被拒绝。
以前到底会发生什么
按 changelog 的描述,旧版本的 Edit / NotebookEdit 在这类文件上做一次编辑,会把文件里每一个非 ASCII 字符都替换掉。也就是说,Claude 只改了其中一处,写回去时没动过的中文也一起坏了,只剩 ASCII 部分保持原样。
麻烦在于这种损坏不太显眼:
- 编辑本身「成功」了,Claude 也会汇报改好了;
- 你在终端里看 diff,可能只觉得「怎么改了这么多行」;
- 等编译、运行或者别人打开文件,才发现注释、字符串、界面文案全成了乱码。
如果文件没进 git,或者已经和其他改动一起提交,恢复起来就很痛苦。
现在的行为
2.1.296 起,Edit 和 NotebookEdit 发现目标文件不是合法 UTF-8 时,不再硬改,而是拒绝这次编辑。换句话说:
- 文件保持原样,不会被悄悄写坏;
- Claude 会得到「编辑被拒」的结果,需要换个办法处理;
- UTF-8 文件(包括带中文的)不受影响,照常编辑。
这是一个「宁可不改,也不改坏」的修复。对 Windows 用户和维护老代码的团队尤其重要。
老项目怎么办:先转码
遇到被拒的情况,最干净的做法是把文件统一转成 UTF-8,再让 Claude 正常编辑。
确认编码:
file -i src/legacy/Config.java转成 UTF-8(GBK 举例):
iconv -f GBK -t UTF-8 src/legacy/Config.java > /tmp/Config.java && mv /tmp/Config.java src/legacy/Config.java批量转换前先提交一次,方便对比和回退。转完后检查一下构建配置:比如 Java 项目的编译编码、IDE 的文件编码设置,避免它们还按 GBK 读。
必须保留原编码时: 有些文件(被旧系统按 GBK 读取的配置、外部约定的数据文件)不能改编码。这时可以在 CLAUDE.md 里写明哪些目录是 GBK,并让 Claude 用 Bash 调 iconv 先转出 UTF-8 副本、改完再转回,而不是直接用 Edit 动原文件。转回之后记得自己 diff 确认。
同一条线上的几次编码修复
Claude Code 这一年陆续修过不少编码相关的问题,可以对照看:
| 版本 | 修复 |
|---|---|
| 2.1.94 | stream-json 输入输出在分块边界切开 UTF-8 序列时,中文等多字节文字被写成 U+FFFD |
| 2.1.214 | Windows 上 PowerShell 工具里的 Python 脚本读非 UTF-8 标准输入时报 UnicodeDecodeError;PowerShell 5.1 下 >、>> 写出 UTF-16LE 文件 |
| 2.1.239 | 以 UTF-8 BOM 开头的 agents、skills、commands .md 文件被静默忽略 |
| 2.1.296 | Edit / NotebookEdit 改坏非 UTF-8 文件,改为拒绝编辑 |
Windows 环境的更多配置建议,可以看 Windows 环境配置。
小结
- 2.1.296 起,Edit / NotebookEdit 遇到 GBK、Shift-JIS、Windows-1252 等非 UTF-8 文件会拒绝编辑,不再把非 ASCII 字符全部替换掉。
- 被拒时优先把文件转成 UTF-8;必须保留原编码的,用
iconv转副本的方式处理,并在CLAUDE.md里写清楚。 - 用旧版本改过 GBK 文件的,建议回头用 git diff 检查一下有没有被改花的中文。
升级后用 claude --version 确认 ≥ 2.1.296。