字符编码是什么

举个具体例子:字符『A』的ASCII编号是65(十进制),二进制是 01000001。当程序说「把这个字节当成字符显示」时,计算机会查ASCII表,65对应『A』,于是屏幕上出现A。

问题来了:不同国家有不同的字符,ASCII的128个位置远远不够。于是各国开始搞自己的编码标准:

  • 中国:GB2312 → GBK → GB18030
  • 日本:Shift-JIS
  • 韩国:EUC-KR
  • 台湾:Big5

这就导致一个文件在中国电脑上打开正常,在日本电脑上打开就乱码了。Unicode就是为了解决这个问题而生的——一个字符集覆盖全人类文字

UTF-8 编码原理(重点)

UTF-8是变长编码,用1-4个字节表示一个Unicode字符:

Unicode范围UTF-8字节数二进制格式示例
U+0000~U+007F1字节0xxxxxxxASCII字符(A、1)
U+0080~U+07FF2字节110xxxxx 10xxxxxx部分欧洲字符
U+0800~U+FFFF3字节1110xxxx 10xxxxxx 10xxxxxx中文、日文(大部分)
U+10000以上4字节11110xxx 10xxxxxx ...emoji、生僻汉字

这就是为什么中文在UTF-8里占3个字节,而英文只占1个。这个设计很聪明:ASCII字符在UTF-8里和ASCII编码完全一样,所以UTF-8完全兼容ASCII。

乱码问题排查清单

  1. 检查文件本身编码:用VS Code打开,右下角会显示文件编码,点击可以转换
  2. 检查HTTP响应头:确保有 Content-Type: text/html; charset=utf-8
  3. 检查HTML head:确保有 <meta charset="UTF-8">
  4. 检查数据库:MySQL要确认表/字段的字符集是 utf8mb4(不是 utf8
  5. 检查代码文件编码:Python文件开头加 # -*- coding: utf-8 -*-,JavaScript文件保存为UTF-8

常见编码相关工具

工具用途
Base64 编码把二进制数据(图片等)变成可打印ASCII字符
URL 编码把特殊字符(空格、中文)转成 %XX 格式
HTML 实体编码把 < 转成 &lt;(防止XSS和显示问题)

Python 3 的字符编码处理

# Python 3 的 str 是 Unicode,bytes 是字节串
text = "你好"           # str 类型(Unicode)
data = text.encode("utf-8")  # 编码成 bytes
text2 = data.decode("utf-8") # 解码回 str

# 文件读写要指定编码
with open("file.txt", "r", encoding="utf-8") as f:
    content = f.read()

# 错误做法:不指定编码(用系统默认,Windows是GBK)
with open("file.txt", "r") as f:  # 可能乱码
    content = f.read()

常见问题 FAQ

MySQL 的 utf8 有什么坑?

MySQL的 utf8 只支持最多3字节,emoji(4字节)存不进去,会报错 Incorrect string value。用 utf8mb4 替代,它是真正的UTF-8。这个坑让无数开发者掉进去过。

Windows 记事本的「带有 BOM 的 UTF-8」是什么?

BOM(Byte Order Mark)是文件开头的几个字节(EF BB BF),用来标记这是UTF-8文件。标准UTF-8不需要BOM,但Windows记事本默认加BOM。有些Linux工具(如gcc、Python解释器)不认识BOM,会导致奇怪的错误。建议保存时选「UTF-8 无 BOM」。

emoji 在数据库里怎么存?

emoji是4字节UTF-8字符,需要数据库字段支持utf8mb4。MySQL需要:1. 数据库/表/字段字符集设为 utf8mb4;2. 连接时也指定 utf8mb4(JDBC URL里加 characterEncoding=utf8mb4)。