一文说透字符编码:乱码到底是怎么产生的
当前位置:点晴教程→知识管理交流
→『 技术文档交流 』
数据库里明明是一段正常中文。 接口返回也没问题。 结果导出成 CSV ,用 Excel 一打开,全变成了: 这类问题很烦。 因为数据通常没有丢,程序也没崩,只是某个环节“理解错了”。你改字体没用,换编辑器偶尔又正常,于是开始怀疑数据库、操作系统,甚至怀疑文件坏了。 问题其实没那么玄。 乱码的本质,是写入和读取使用了不同的字符编码。 同一串字节,按 UTF-8 解读是一回事,按 GBK 、 Latin-1 解读又是另一回事。 乱码不是文字疯了。 是两边没对上暗号。 计算机存的不是文字,是数字屏幕上看到的“你”“A”“🙂”,对计算机来说都不是字形。 它先要给每个字符分配一个编号。 Unicode 把这个编号叫作码点,也就是 code point 。 比如: 码点解决的是: 但码点还不能直接写进文件。 文件、内存和网络传输最终都要落成字节。于是还需要一套规则,把码点转换成字节序列。 这套规则才叫字符编码。 所以要分清三个东西: 很多乱码问题,就是把这三层揉成了一团。
UTF-8 到底做了什么UTF-8 是 Unicode 的一种编码方式。 它不是字符集的另一个名字,也不是“中文编码”。 它做的事情很具体:把 Unicode 码点编码成 1 到 4 个字节。 常见情况: 比如字母 汉字“你”: 这也是为什么“一个字符等于一个字节”是错的。 英文看起来经常成立,只是因为 ASCII 字符在 UTF-8 中恰好占一个字节。 换成中文、 Emoji 、少数字符,立刻翻车。 乱码是怎么一步步产生的假设“你好”按 UTF-8 写进文件。 对应的字节是: 如果读取方也按 UTF-8 解码,就能还原成“你好”。 链路是: 没问题。 但如果读取方把这串 UTF-8 字节当成 Latin-1 或其他编码处理,得到的字符就会变成另一批符号。 链路变成: 注意,原始字节可能完全没坏。 错的是解释方式。 这也是为什么有些乱码还能“救回来”:只要原始字节没有在错误转换中丢失,换回正确编码重新解码就行。 怕的是二次写入。 乱码出现后,如果程序又把乱码按另一种编码保存一次,字节会被重新改写。来回折腾几轮,数据就真烂了。
为什么改字体解决不了乱码字体解决的是“这个字符怎么画”。 编码解决的是“这些字节代表哪个字符”。 顺序完全不同: 如果解码阶段已经把 还有一种情况是方框、问号或空白: 这不一定是编码错。 可能是字符已经正确解码,但当前字体不包含对应字形。 区分方法很实用: 别混着查。 BOM 又是什么很多 Windows 或 Excel 相关乱码,会绕到 BOM 。 BOM 是 Byte Order Mark ,字节顺序标记。 在 UTF-16 、 UTF-32 里,它可以帮助识别字节序。 UTF-8 没有大小端问题,但有些程序会用 UTF-8 BOM 来判断文件编码。 UTF-8 BOM 是三个字节: 这也是为什么同一个 UTF-8 CSV : 不是 UTF-8 变了。 是读取软件判断编码的方式不同。 但 BOM 也不是到处乱加。 有些脚本、协议或解析器会把 BOM 当成正文开头,导致第一列列名多出一个不可见字符。看不见,查半天。挺阴。 浏览器和接口为什么也会乱码HTTP 响应可以通过 或者: 浏览器收到字节后,会根据响应头、 HTML 元信息或自身判断选择解码方式。 HTML 页面通常还会写: 如果文件实际是 UTF-8 ,但响应头硬说是 GBK ,浏览器就可能按错误规则解码。 接口也一样。 服务端生成的是 UTF-8 JSON ,中间网关改错了 链路越长,越容易有人自作聪明。 数据库里要看四个位置数据库乱码,不能只看表字段。 至少要检查: 以 MySQL 为例,可以查看: 还要注意 MySQL 历史上的 要完整支持 Unicode ,通常应该使用: 如果字段还是旧的 这类问题不是表情包太新潮。 是数据库当年留了历史债。 字符长度和字节长度不是一回事这是工程里另一个大坑。 假设字符串是: 从“用户看到的字符”看,似乎是 4 个字符。 但在 UTF-8 中,字节数可能是: 所以: 不能混为一谈。 还有更麻烦的:用户眼中的一个 Emoji ,内部可能由多个码点组合而成。家庭、肤色、职业等 Emoji ,经常不是一个简单码点。 “字符串长度”这件事,看起来基础,深挖下去挺潮湿的。 出现乱码时怎么排查别一上来就批量转码。 按链路查。 第一步,确认原始字节。 Linux 下可以看十六进制: 或者: 第二步,判断文件编码: 这个结果只是推测,不是圣旨,但能提供线索。 第三步,明确写入方用什么编码。 第四步,明确读取方按什么编码解码。 第五步,检查中间是否发生过二次转换: 需要转换时可以用 重点是 猜错了再转一次,只会把现场踩得更乱。
怎么理解字符编码字符编码不是“中文显示设置”。 它是一份约定: 只要写入方和读取方遵守同一份约定,文字就正常。 一边写 UTF-8 ,另一边按 GBK 猜,乱码就来了。 所以以后再遇到乱码,不要先改字体,也不要盲目转码。 先问三件事: 把这条链路对齐,乱码就没那么神秘了。 阅读原文:点击这里 该文章在 2026/7/17 18:22:53 编辑过 |
关键字查询
相关文章
正在查询... |