📊 字符编码详解:UTF-8、GBK 与乱码问题全解析

发布于 2026 年 8 月 · 阅读约 6 分钟

什么是字符编码

计算机内部只能存储二进制数据,字符必须以数字形式表示,字符编码就是这个"字符与数字一一对应"的规则。例如,大写字母 A 在 ASCII 编码中对应十进制 65。不同的编码方案有不同的字符覆盖范围和字节表示方式,理解它们之间的关系是解决乱码问题的关键。

常见编码方案

ASCII

ASCII(美国信息交换标准代码)是最基础的编码,用 7 位二进制(128 个字符)表示英文字母、数字、标点和控制字符。它只覆盖英文,无法表示中文。每个 ASCII 字符在存储时占 1 字节。

GBK / GB2312

GB2312 是中国制定的汉字编码标准,GBK 是它的扩展,兼容 GB2312,并增加了更多汉字和符号。GBK 使用 1-2 字节变长编码:ASCII 字符占 1 字节,汉字占 2 字节。GBK 编码的中文在中文环境(如部分旧版 Windows)中常见。

UTF-8

UTF-8 是 Unicode 的变长编码实现,是当今互联网的事实标准。它使用 1-4 字节表示一个字符:ASCII 字符占 1 字节(与 ASCII 完全兼容),大部分常用汉字占 3 字节,生僻字和 emoji 占 4 字节。UTF-8 的优势是兼容 ASCII、无字节序问题、自同步。

UTF-16

UTF-16 用 2 或 4 字节表示字符,是 JavaScript 内部字符串的存储方式(现代引擎多为 UTF-16)。它处理 BMP(基本多文种平面)字符时效率较高,但有字节序(大小端)问题,网络传输时需要指定 BOM。

为什么会出现乱码

乱码的根源是"编码与解码不一致":一段文本用 A 编码方式写入,却用 B 编码方式读取。常见情况:

  • 文件保存为 UTF-8,但用 GBK 编码的编辑器打开,中文显示为"锟斤拷"或"�"
  • 网页声明 UTF-8,但内容实际是 GBK,导致浏览器渲染乱码
  • 数据库连接字符集配置错误,导致写入和读取编码不一致
  • Base64 编码时使用一种编码,解码时使用另一种

常见乱码现象对照

  • "锟斤拷" — UTF-8 文本被误用 GBK 读取的典型结果
  • "烫烫烫" — 未初始化内存的调试填充值,常出现在 C/C++ 调试场景
  • "鈥滄灄" 等 — UTF-8 被误认为 Latin-1/CP1252 读取
  • 出现问号 ? — 字符在目标编码中不存在,通常发生在转换过程中丢失信息

如何避免中文乱码

1. 统一使用 UTF-8

现代 Web 开发的最佳实践是全链路统一 UTF-8:HTML 文件声明 <meta charset="UTF-8">,数据库连接指定 utf8mb4,API 请求和响应使用 UTF-8。这样可以避免绝大多数编码问题。

2. 注意字节数与字符数

在 UTF-8 中,一个中文字符占 3 字节,一个英文字符占 1 字节。当你需要计算存储空间或数据库字段长度(如 VARCHAR(255) 是 255 字符还是 255 字节)时,要清楚这个区别。使用我们的 文本统计工具 可以同时查看字符数和字节数。

3. 处理 Base64 时保持一致

Base64 编码的是原始字节。如果一段中文用 UTF-8 编码后做 Base64,解码时必须先 Base64 解码再用 UTF-8 还原文本,否则会出现乱码。我们的 Base64 工具 已统一使用 UTF-8 处理,避免这个问题。

4. 查看文件编码

遇到乱码文件时,先用工具检测文件实际编码(如 VS Code 右下角、Notepad++ 的编码菜单),再以正确编码重新打开或转换。不要盲目猜测,避免二次损坏。

字节数计算的实用价值

文本统计中的"字节数"指标在多个场景非常实用:估算数据库字段容量、计算 API 请求体大小、判断日志文件规模、评估网络传输量。一个"在线工具箱"(5 个汉字)在 UTF-8 下占 15 字节,而 15 个英文字母只占 15 字节——中英文混排文本的字节数需要逐字计算。

小结

字符编码是开发中看似基础、实则影响深远的知识。理解 ASCII、GBK、UTF-8 的区别,掌握"编码与解码一致"的核心原则,并养成全链路 UTF-8 的习惯,就能从根本上避免乱码问题。