LOGO 首页 OA教程 ERP教程 模切知识交流 PMS教程 CRM教程 技术文档 其他文档  
 
网站管理员

一文说透字符编码:乱码到底是怎么产生的

admin
2026年7月17日 18:21 本文热度 46

数据库里明明是一段正常中文。

接口返回也没问题。

结果导出成 CSV ,用 Excel 一打开,全变成了:

ä½ å¥½ï¼Œä¸–ç•Œ

这类问题很烦。

因为数据通常没有丢,程序也没崩,只是某个环节“理解错了”。你改字体没用,换编辑器偶尔又正常,于是开始怀疑数据库、操作系统,甚至怀疑文件坏了。

问题其实没那么玄。

乱码的本质,是写入和读取使用了不同的字符编码

同一串字节,按 UTF-8 解读是一回事,按 GBK 、 Latin-1 解读又是另一回事。

乱码不是文字疯了。

是两边没对上暗号。

计算机存的不是文字,是数字

屏幕上看到的“你”“A”“🙂”,对计算机来说都不是字形。

它先要给每个字符分配一个编号。

Unicode 把这个编号叫作码点,也就是 code point 。

比如:

A  -> U+0041
你 -> U+4F60
🙂 -> U+1F642

码点解决的是:

这个字符是谁

但码点还不能直接写进文件。

文件、内存和网络传输最终都要落成字节。于是还需要一套规则,把码点转换成字节序列。

这套规则才叫字符编码。

所以要分清三个东西:

字符:人看到的符号
码点:字符在 Unicode 中的编号
编码:把编号转换成字节的规则

很多乱码问题,就是把这三层揉成了一团。

UTF-8 到底做了什么

UTF-8 是 Unicode 的一种编码方式。

它不是字符集的另一个名字,也不是“中文编码”。

它做的事情很具体:把 Unicode 码点编码成 1 到 4 个字节。

常见情况:

ASCII 字符:1 字节
大部分拉丁扩展字符:2 字节
常用中文:3 字节
部分 Emoji:4 字节

比如字母 A

字符:A
码点:U+0041
UTF-8 字节:41

汉字“你”:

字符:你
码点:U+4F60
UTF-8 字节:E4 BD A0

这也是为什么“一个字符等于一个字节”是错的。

英文看起来经常成立,只是因为 ASCII 字符在 UTF-8 中恰好占一个字节。

换成中文、 Emoji 、少数字符,立刻翻车。

乱码是怎么一步步产生的

假设“你好”按 UTF-8 写进文件。

对应的字节是:

E4 BD A0 E5 A5 BD

如果读取方也按 UTF-8 解码,就能还原成“你好”。

链路是:

字符
  ↓ UTF-8 编码
字节
  ↓ UTF-8 解码
字符

没问题。

但如果读取方把这串 UTF-8 字节当成 Latin-1 或其他编码处理,得到的字符就会变成另一批符号。

链路变成:

字符
  ↓ UTF-8 编码
字节
  ↓ 错误编码解码
乱码

注意,原始字节可能完全没坏。

错的是解释方式。

这也是为什么有些乱码还能“救回来”:只要原始字节没有在错误转换中丢失,换回正确编码重新解码就行。

怕的是二次写入。

乱码出现后,如果程序又把乱码按另一种编码保存一次,字节会被重新改写。来回折腾几轮,数据就真烂了。

为什么改字体解决不了乱码

字体解决的是“这个字符怎么画”。

编码解决的是“这些字节代表哪个字符”。

顺序完全不同:

字节
  ↓ 解码
字符
  ↓ 字体渲染
屏幕上的字形

如果解码阶段已经把 E4 BD A0 认成了错误字符,后面换再漂亮的字体,也只是在把错误字符画得更清楚。

还有一种情况是方框、问号或空白:

□
�
?

这不一定是编码错。

可能是字符已经正确解码,但当前字体不包含对应字形。

区分方法很实用:

出现稳定的奇怪字符:优先怀疑编码
出现方框或缺字符号:优先怀疑字体

别混着查。

BOM 又是什么

很多 Windows 或 Excel 相关乱码,会绕到 BOM 。

BOM 是 Byte Order Mark ,字节顺序标记。

在 UTF-16 、 UTF-32 里,它可以帮助识别字节序。 UTF-8 没有大小端问题,但有些程序会用 UTF-8 BOM 来判断文件编码。

UTF-8 BOM 是三个字节:

EF BB BF

这也是为什么同一个 UTF-8 CSV :

文本编辑器打开正常
Excel 打开乱码
加上 BOM 后 Excel 又正常

不是 UTF-8 变了。

是读取软件判断编码的方式不同。

但 BOM 也不是到处乱加。

有些脚本、协议或解析器会把 BOM 当成正文开头,导致第一列列名多出一个不可见字符。看不见,查半天。挺阴。

浏览器和接口为什么也会乱码

HTTP 响应可以通过 Content-Type 声明字符编码:

Content-Type: text/html; charset=utf-8

或者:

Content-Type: application/json; charset=utf-8

浏览器收到字节后,会根据响应头、 HTML 元信息或自身判断选择解码方式。

HTML 页面通常还会写:

<meta charset="UTF-8">

如果文件实际是 UTF-8 ,但响应头硬说是 GBK ,浏览器就可能按错误规则解码。

接口也一样。

服务端生成的是 UTF-8 JSON ,中间网关改错了 Content-Type,或者客户端强制按本地编码读取,都可能乱码。

链路越长,越容易有人自作聪明。

数据库里要看四个位置

数据库乱码,不能只看表字段。

至少要检查:

数据库默认字符集
表和字段字符集
客户端连接字符集
应用程序使用的编码

以 MySQL 为例,可以查看:

SHOW VARIABLES LIKE 'character_set%';
SHOW VARIABLES LIKE 'collation%';

还要注意 utf8 和 utf8mb4

MySQL 历史上的 utf8 最多支持 3 字节,不能完整存储需要 4 字节的 Unicode 字符,比如不少 Emoji 。

要完整支持 Unicode ,通常应该使用:

utf8mb4

如果字段还是旧的 utf8,用户昵称里放个 Emoji ,写入就可能失败或被截断。

这类问题不是表情包太新潮。

是数据库当年留了历史债。

字符长度和字节长度不是一回事

这是工程里另一个大坑。

假设字符串是:

你好A🙂

从“用户看到的字符”看,似乎是 4 个字符。

但在 UTF-8 中,字节数可能是:

你:3
好:3
A:1
🙂:4
合计:11 字节

所以:

字符限制
字节限制
数据库字段长度
网络报文长度
文件大小

不能混为一谈。

还有更麻烦的:用户眼中的一个 Emoji ,内部可能由多个码点组合而成。家庭、肤色、职业等 Emoji ,经常不是一个简单码点。

“字符串长度”这件事,看起来基础,深挖下去挺潮湿的。

出现乱码时怎么排查

别一上来就批量转码。

按链路查。

第一步,确认原始字节。

Linux 下可以看十六进制:

xxd file.txt | head

或者:

hexdump -C file.txt | head

第二步,判断文件编码:

file -i file.txt

这个结果只是推测,不是圣旨,但能提供线索。

第三步,明确写入方用什么编码。

第四步,明确读取方按什么编码解码。

第五步,检查中间是否发生过二次转换:

数据库连接
消息队列
HTTP 网关
文件导入导出
日志采集
Excel

需要转换时可以用 iconv

iconv -f GBK -t UTF-8 input.txt > output.txt

重点是 -f 必须写原始编码。

猜错了再转一次,只会把现场踩得更乱。

怎么理解字符编码

字符编码不是“中文显示设置”。

它是一份约定:

某个字符
应该被编码成哪些字节
这些字节又该怎样还原成字符

只要写入方和读取方遵守同一份约定,文字就正常。

一边写 UTF-8 ,另一边按 GBK 猜,乱码就来了。

所以以后再遇到乱码,不要先改字体,也不要盲目转码。

先问三件事:

原始字符是什么
写入时用了什么编码
读取时用了什么编码

把这条链路对齐,乱码就没那么神秘了。


阅读原文:点击这里


该文章在 2026/7/17 18:22:53 编辑过
关键字查询
相关文章
正在查询...
点晴ERP是一款针对中小制造业的专业生产管理软件系统,系统成熟度和易用性得到了国内大量中小企业的青睐。
点晴PMS码头管理系统主要针对港口码头集装箱与散货日常运作、调度、堆场、车队、财务费用、相关报表等业务管理,结合码头的业务特点,围绕调度、堆场作业而开发的。集技术的先进性、管理的有效性于一体,是物流码头及其他港口类企业的高效ERP管理信息系统。
点晴WMS仓储管理系统提供了货物产品管理,销售管理,采购管理,仓储管理,仓库管理,保质期管理,货位管理,库位管理,生产管理,WMS管理系统,标签打印,条形码,二维码管理,批号管理软件。
点晴免费OA是一款软件和通用服务都免费,不限功能、不限时间、不限用户的免费OA协同办公管理系统。
Copyright 2010-2026 ClickSun All Rights Reserved  粤ICP备13012886号-2  粤公网安备44030602007207号