字符编码详解
基本概念
- 字符(character): 人类可读的符号,比如
A、中、😊等。 - 字节(Byte):计算机存储的基本单位,8位二进制数。
- 编码(Encoding):将字符映射为字节的规则或标准。
字符编码就是:字符 <–> 字节 的映射规则。
字符编码的历史演进
| 年代 | 编码名称 | 特点 | 问题 |
|---|---|---|---|
| 1963 | ASCII | 7位,128个字符,英文够用 | 不支持其他语言 |
| 1980s | ISO-8859-1 (Latin-1) | 8位,扩展了西欧字符 | 不支持中文、日文等 |
| 1990s | GB2312 | 中国国标,支持简体中文 | 字符集小,生僻字没有 |
| 1995 | GBK | GB2312 扩展,支持繁体、生僻字 | 仅中文,跨平台差 |
| 2000 | GB18030 | 国标强制标准,兼容Unicode | 复杂,部分系统不支持 |
| 1991 | Unicode 诞生 | 统一全球字符,字符集无限大 | 编码方案未定 |
| 1993 | UTF-16 | Unicode 编码方案之一 | 固定2字节,浪费空间 |
| 2008 | UTF-8 成为主流 | 变长编码,节省空间,兼容ASCII | 无缺点,现已成为互联网标准 |
三大主流字符编码
ASCII (美国信息交换标准代码)
- 范围:0~127 (7位)
- 内容:英文字母、数字、基本标点符号和控制字符
- 示例:
1
'A' -> 65(10进制) -> 01000001(二进制)
GBK(中国国家标准扩展编码)
- 双字节编码:英文字符1字节,中文字符2字节
- 兼容ASCII:英文字符不变
- 问题:
- 不支持日文、韩文等其他语言
- 跨平台乱码常见(Windows 默认编码)
UTF-8 (8位可变长度编码)
- 变长编码:
- 1字节:ASCII字符 (0~127)
- 2字节:拉丁文扩展等(128~2047)
- 3字节:中日韩字符(2048~65535)
- 4字节:少数生僻字、表情符号等(65536及以上)
- 优点:
- 兼容 ASCII
- 节省空间(英文文本小)
- 全球通用,支持所有语言字符
- 示例:
1
2
3
'A' -> 41(十六进制)
'中' -> E4 B8 AD
'😊' -> F0 9F 98 8A
UTF-8 与 Unicode 的关系:Unicode 是字符集,UTF-8 是编码方式。
编码与解码的过程
编码 (Encoding)
把字符变成字节
1
2
3
text = "中文"
byte_data = text.encode('utf-8')
print(byte_data) # b'\xe4\xb8\xad\xe6\x96\x87'
解码 (Decoding)
把字节还原成字符
1
2
3
byte_data = b'\xe4\xb8\xad\xe6\x96\x87'
text = byte_data.decode('utf-8')
print(text) # 中文
乱码的本质
乱码 = 编码和解码用的规则不一致
示例:
1
2
3
4
5
text = "中文"
byte_data = text.encode('utf-8')
# 错误地用 GBK 解码
print(byte_data.decode('gbk')) # 输出:涓枃(乱码)
BOM (字节顺序标记)
BOM 是字节顺序标记(Byte Order Mark),用于标识文本文件的编码格式。
是一段放在文件最开头的特殊字节序列,用来告诉别人:“我这份数据到底用的是什么 Unicode 编码方案,以及字节序是大端还是小端。”
总结 (字符编码家谱)
1
2
3
4
5
6
7
8
9
10
ASCII
│
├── ISO-8859-1(Latin-1)
│
├── GB2312 → GBK → GB18030(中文)
│
└── Unicode
├── UTF-8(互联网标准)
├── UTF-16(Windows、Java)
└── UTF-32(很少用)