01 背景
为某客户做信锐 AC 监控时,AC 下纳管的 AP 名字显示为 16 进制字串(形如 E5 95 86 E5 8A A1 E9 83 A8),客户反馈看不懂其代表的含义,要求将其转化为可读的中文名称。
02 原因
通过 SNMP 获取 AP 名称时存在两种情况:
- 如果 AP 的名字未被更改,获取到的是 MAC 地址(不需要转化)
- 如果 AP 的名字已被更改,获取到的是 UTF-8 编码的 16 进制数(需要转化为中文)
矛盾在于:如果 AP 名字被更改过,应该做转化;如果未被更改,则不应该做转化。于是研发人员将这个判断工作交给了实施团队——根据实际情况决定是否转化。
历史上有近 10 个客户使用了信锐 AC,都是在实施过程中人工识别和转化的。那有没有办法在代码里自动兼容这两种情况呢?答案是可以的。因为 UTF-8 编码有固定规则,完全可以通过程序区分 16 进制数是 MAC 地址还是 UTF-8 编码。
具体代码实现不在此赘述,但有的同学一提到 ASCII、GBK、GB2312、UTF、16 进制就抓瞎,所以把涉及到的编码知识在团队内做一次系统性总结和普及。
03 知识点拓展
(1)16 进制
16 进制是数字的一种呈现形式,并不是独立的编码体系。
- 数字
10的 16 进制表示为A - 数字
10的二进制表示为1010
16 进制常用于简化二进制的书写,每个 16 进制位对应 4 个二进制位。
(2)ASCII 码
ASCII(美国信息交换标准代码)制定于 1960 年代,将英文字符与二进制一一对应。
16进制 30→ 数字字符016进制 61→ 英文字母a
ASCII 码只覆盖了英文字母、数字和常用符号,共 128 个字符,无法表示中文等非英文字符。
(3)Unicode
全球有数百种文字,计算机只认识数字。如果没有统一的表示方式,同一个汉字在不同系统可能用不同编号表示,导致乱码混乱。
Unicode 的出现解决了这个问题:它是一个全球统一的字符集,把世界上所有的文字都定义了唯一的数字表示方式(称为"码点",Code Point)。例如:
- 汉字"你"的 Unicode 码点为
U+4F60 - 汉字"我"的 Unicode 码点为
U+6211
(4)Unicode 的问题
Unicode 定义了字符的唯一编号,但并未规定如何在计算机中存储和传输。直接使用 Unicode 码点存储存在两个问题:
- 无法确定字符边界:一串字节无法识别表示几个字符
- 存储空间膨胀:通过补零使所有字符占用统一长度(如 4 字节),会造成存储空间和网络传输带宽的严重浪费
因此,Unicode 最终作为"字符的表示标准"而非"存储编码方式"存在。
(5)UTF 编码
随着互联网普及,UTF(Unicode Transformation Format)编码方式应运而生,真正将 Unicode 表示方式转换为实用的存储编码。
UTF-8 采用变长编码:根据字符的 Unicode 码点范围,使用 1~4 个字节来表示一个字符。
a)单字节字符(英文字母、数字等)
编码格式:0xxxxxxx
- 第一位固定为
0,后面 7 位是 Unicode 码点 - 对于英文单字符,UTF-8 编码与 ASCII 完全兼容
b)多字节字符(N 字节,如中文)
编码格式:
- 第 1 字节:前 N 位全为
1,第 N+1 位为0,剩余8-N-1位填充 Unicode 码点高位 - 后续字节:前两位固定为
10,剩余 6 位填充 Unicode 码点的后续位
UTF-8 字节范围与字符类型对应关系:
| Unicode 码点范围 | UTF-8 字节数 | 编码格式 |
|---|---|---|
| U+0000 ~ U+007F | 1 字节 | 0xxxxxxx |
| U+0080 ~ U+07FF | 2 字节 | 110xxxxx 10xxxxxx |
| U+0800 ~ U+FFFF | 3 字节 | 1110xxxx 10xxxxxx 10xxxxxx |
| U+10000 ~ U+10FFFF | 4 字节 | 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx |
c)实例:汉字"你"的 UTF-8 编码
- “你"的 Unicode 码点:
U+4F60,二进制为0100 1111 0110 0000 - 码点落在
U+0800 ~ U+FFFF范围,使用 3 字节编码 - 编码格式:
1110xxxx 10xxxxxx 10xxxxxx - 填充码点二进制后得:
1110 0100 1011 1101 1010 0000 - 对应 16 进制:
E4 BD A0
这就是为什么"你"的 UTF-8 编码是 E4BDA0。
04 题外话
理解 Unicode 的核心:它是文字的唯一数字化表示方式,也叫码点(Code Point)。Unicode 只负责"定义字符编号”,不负责"如何存储"。
理解 UTF 的核心:它是"把 Unicode 码点做转换,从而让其在网络传输、文件保存等场景中没有歧义的编码方式"。
其他相关编码方式:
- UCS-2:双字节编码,用固定 2 个字节表示 Unicode 字符(已被 UTF-16 替代)
- UCS-4:4 字节编码,用固定 4 个字节表示 Unicode 字符(存储浪费)
- GBK/GB2312:中国国家标准,兼容 ASCII,用 1~2 字节表示字符,但不兼容其他语言的 Unicode 标准
回到最初的问题:信锐 AC 返回的 E5 95 86 E5 8A A1 E9 83 A8 正是中文"商务部"的 UTF-8 编码,只需将其按 UTF-8 规则解码即可还原为可读的中文名称。