ai砰砰无乱码do麻烦
今日精选 · SINGLE POST

凌晨两点十七分,那段日志终于不砰砰了

一次把 GBK 和 UTF-8 从互咬到和解的全过程。顺便说说,为什么 AI 生成的东西,总在细节处发出那种「砰砰」的乱码声。

林小满 发布于 2026-05-05 阅读约 9 分钟
[02:17] stdout: 0xE4 0xBD 0xA0 ✓
[02:17] stdout: 0xB0 0xA1 0xB0 0xA1 ✗
编码现场

ai砰砰无乱码do麻烦

凌晨两点十七分,我盯着终端里那行一直闪的报错,手里那杯第三杯冷掉的咖啡已经结了膜。

报错来自一台跑了六年的老服务器。日志文件里有半截中文,前半段正常,后半段变成一串方块,中间还夹着几个「砰砰」——其实不是砰砰,是终端把 0xB0 0xA1 这样的字节读错了位置,一格一格地蹦出来,看着就像有人在屏幕里敲铁皮。

我先把日志拉下来,用 file 看了一眼。它说这是 ISO-8859。这就麻烦了。ISO-8859 不会报错,它只会把每个字节都当合法字符,于是所有错位都被默默咽下去,再吐成一堆问号和怪符号。

先分清哪一段是好的

我把文件按行切开,只保留带中文的那些行,丢给一个小脚本逐行试解码。UTF-8、GB18030、Big5 各跑一遍,统计「替换字符」出现的次数。结果很有意思:前 1200 行在 GB18030 下单次替换为零,从 1201 行开始,UTF-8 反而最干净。

也就是说,这个文件是两个人的手笔,中间被谁用另一种编码追加过。拼接本身不新鲜,麻烦的是它们中间没有分隔标记,像两段不同方言的录音直接焊在一起。

深色屏幕上的代码与终端输出,代码行整齐排列
凌晨的终端。屏幕上那半截中文,是这次全部麻烦的起点。

把 AI 拉进来,然后失望一次

我本来想省点事,把这 4000 多行日志丢给一个常用的模型,让它判断编码边界。它回答得很快,语气也很笃定:从第 987 行开始是 UTF-8。我照着切,结果第 988 行还是乱码。它把「看起来像汉字的高频字节对」当成了判断依据,而不是真正去验证字节序列。

这就是我说的「ai砰砰」。不是它答不出来,是它在细节够不着的地方,用一种非常自信的方式发出噪音。你知道它在猜,它还偏要给你一个精度感十足的答案。

我后来在自己笔记里写:AI 不会让错误变少,它只会让错误变得更像正确答案。 —— 我的工作笔记,2026 年 5 月 4 日,第 47 页

最后是笨办法救的场

真正定位边界的,是一个四十行的 Python 脚本:逐字节扫描,遇到 UTF-8 合法序列就前推,不合法就退一格再试 GB18030。第 1200 行的那个 0x0A 换行符成了分水岭,两边各自解码,再拼回去。跑完是两点十七分,速度和报错时间几乎一样。

改完的日志读起来很顺,像一句被重新断句的长句子。我截了图发给朋友老周,他回我三个字:「值了吧。」我说值,就是眼睛有点干。

顺便说一句,我认同「乱码不是玄学,是懒」。绝大多数乱码都不是编码本身的错,是有人图省事,没在边界处留一行注释、没在写入时声明字符集。这类麻烦,用不着 AI,用不着什么神奇工具,用一行 charset=utf-8 就能挡掉一大半。

如果你也在修类似的东西,可能用得着这几页我翻过的记录:9922dy.com 上有一篇讲字节序的旧文,xg0072.cc西瓜 里那位作者对 Big5 的判断挺细,极速大师.cn 则记了一次和我几乎一样的双编码拼接事故。


今天很累。不是那种被掏空的累,是走了很长一段路、鞋底磨薄了、回头看却发现路其实不长的累。问题本身只有一行代码那么大,可它藏在 4128 行里,等你一格格地走过去。

值得。真的。

林小满的头像照
林小满
独立写作者,修编码也修句子。喜欢短句和留白,偶尔在深夜吐槽 AI 的自信。
作者:林小满 · 发布于 2026-05-05