编码基础

返回计算机基础


位、字节、字符

1 bit(位)   = 0 或 1,计算机最小存储单元
8 bit         = 1 Byte(字节),最小寻址单元
1 KB          = 1024 Byte
1 MB          = 1024 KB
1 GB          = 1024 MB

字符 ≠ 字节:字符是人类可读的符号,字节是存储单位,一个字符占几个字节取决于编码方式


常见编码

ASCII

  • 范围:128个字符(英文字母、数字、符号、控制字符)
  • 每个字符 1字节,只用低7位,最高位为0
  • 'A' = 65 = 0100 0001

GBK / GB2312

  • 中国国家标准,向下兼容 ASCII
  • ASCII字符:1字节
  • 汉字:2字节
  • '中' = 0xD6 0xD0(两个字节)

IBM EBCDIC 系列

IBM 大型机(Mainframe)使用的私有编码体系,与 ASCII 不兼容

EBCDIC(Extended Binary Coded Decimal Interchange Code):IBM 1964 年推出,字母 A-Z 不连续排列,与 ASCII 字节值完全不同。

常见 EBCDIC 代码页:

代码页名称覆盖范围
IBM037EBCDIC 美国英语英文、基本符号
IBM500EBCDIC 多语言西欧语言
IBM935EBCDIC 简体中文英文 + 简体汉字(双字节)
IBM937EBCDIC 繁体中文英文 + 繁体汉字(双字节)
IBM939EBCDIC 日语英文 + 日语(双字节)

IBM935 结构

单字节部分:EBCDIC 编码的英文、数字、符号(1字节)
双字节部分:DBCS(Double Byte Character Set)汉字(2字节)

IBM935 是 SBCS + DBCS 混合编码,用移位字符(Shift-In/Shift-Out)区分单双字节区域:

0x0E  → Shift-Out,后续字节按双字节解析
0x0F  → Shift-In,回到单字节 EBCDIC 模式

例:IBM935GBK 同样覆盖简体中文,但字节映射完全不同,两者不可混用。

应用场景:银行、证券、保险等行业的 IBM 大型机系统(z/OS、AS/400),数据交换时需明确指定代码页做转码。


Unicode

Unicode 是字符集,不是编码,给全球所有字符分配唯一码点(Code Point)。

例如:'中' 的码点是 U+4E2D

具体怎么存储由编码方案决定(UTF-8、UTF-16、UTF-32)。

UTF-8(最主流)

变长编码,1~4字节:

字符范围字节数说明
U+0000 ~ U+007F1字节ASCII,完全兼容
U+0080 ~ U+07FF2字节拉丁文、希腊文、阿拉伯文等
U+0800 ~ U+FFFF3字节中文、日文、韩文(CJK)
U+10000 ~ U+10FFFF4字节生僻字、emoji(😊)
英文 'A'  → 1字节:0x41
中文 '中' → 3字节:0xE4 0xB8 0xAD
emoji '😊' → 4字节:0xF0 0x9F 0x98 0x8A

UTF-8 编码规则

1字节:0xxxxxxx
2字节:110xxxxx 10xxxxxx
3字节:1110xxxx 10xxxxxx 10xxxxxx
4字节:11110xxx 10xxxxxx 10xxxxxx 10xxxxxx

'中'(U+4E2D = 0100 1110 0010 1101)为例:

填入3字节模板:1110xxxx 10xxxxxx 10xxxxxx
             11100100 10111000 10101101
             = 0xE4     0xB8     0xAD

UTF-16

  • BMP(基本多文种平面,U+0000~U+FFFF):2字节(包含绝大多数常用汉字)
  • 辅助平面:4字节(代理对)
  • Java 内部 char 用的是 UTF-16,所以 char 占 2 字节
  • 有大端(UTF-16 BE)和小端(UTF-16 LE)之分,文件头用 BOM 区分

UTF-32

  • 所有字符固定 4字节
  • 空间浪费,几乎不用于存储和传输
  • 优点是随机访问简单(第n个字符直接偏移 4n)

编码对比

编码英文汉字特点
ASCII1字节不支持最古老,英文专用
GBK1字节2字节中文环境遗留标准
IBM9351字节(EBCDIC)2字节(DBCS)IBM大型机简体中文,与ASCII不兼容
UTF-81字节3字节互联网标准,兼容ASCII
UTF-162字节2字节Java内部、Windows内部
UTF-324字节4字节定长,浪费空间

常见乱码场景

场景原因解决
页面中文乱码响应编码未指定response.setCharacterEncoding("UTF-8")
读文件乱码文件编码与读取编码不符明确指定 new InputStreamReader(in, "UTF-8")
MySQL 乱码字符集不是 utf8mb4建表和连接都用 utf8mb4
URL 参数乱码GET 参数编码问题URLEncoder.encode(s, "UTF-8")

BOM(Byte Order Mark)

UTF-8 文件有时带 BOM(0xEF 0xBB 0xBF),Linux 环境建议保存为 UTF-8 without BOM