win32相关(字符编码)
字符编码
ASCII编码
ASCII(American Standard Code for Information Interchange,美国信息交换标准代码)是最基础的字符编码标准,用于在计算机和其他设备中表示文本
基本概念
- 7位编码: ASCII使用7位二进制数(共128个编码点,0-127)来表示字符
- 标准ASCII: 0-127的编码范围
- 扩展ASCII: 一些系统使用第8位(共256个编码点),但这不属于标准ASCII
我们新建一个记事输入ABab,保存编码为ASCII编码格式,再用一个二进制文本查看器打开
可以看到大写的A对应ASCII编码中的41,B对应42,小写的a对应62,大写61(这里的都是十六进制,编码表上的是十进制
)
存储方式
在ASCIi编码中计算机中存储一个字符占一个字节,但标准的ASCII码表只有128个字符,即 0 - 7F
后面的 80 - FF 就是扩展ASCII编码
GB2312编码
与ASCII的关系
- 兼容ASCII: 单字节的ASCII字符(0x00-0x7F)在GB2312中保持不变
- 区分规则:
当字节值>0x7F时,与后续字节组合成双字节中文字符
因此GB2312编码的文本中,ASCII字符和中文可以混用
改变之前记事本中的内容,输入中文
保存为ASCII编码用二进制文本工具打开
可以看到中文
被转为二进制编码时,中为:0xD0D6
文为:0xC4CE
由两个1字节拼凑出来一个中文字符,单个字节编码也都在ASCII(扩展)编码范围内
UNICODE编码
Unicode 是一个国际标准,旨在为世界上所有书写系统的每个字符提供一个唯一的数字标识(称为码点/Code Point),解决了
传统编码(如ASCII、GB2312等)的局限性
核心概念
- 码点(Code Point):
- 每个字符被分配一个唯一的数字编号
- 表示形式:
U+
前缀+十六进制数字(如U+4E2D
表示"中") - 范围:
U+0000
到U+10FFFF
(共1,114,112个码位)
- 编码平面:
- 基本多文种平面(BMP): U+0000-U+FFFF(最常用字符)
- 辅助平面: U+10000-U+10FFFF(emoji、罕见汉字等)
如何存储UNICODE
UTF-16 & UTF-8
UNICODE规定了符号是什么, UTF-16或UTF-8则规定了如何储存
UTF-16
在UTF-16的格式下保存,可以看到每个字符占2个字节,那0xFEFF又是什么呢?(UTF-16的存储格式下,一个存储单元占2个字节,如果一个存储单元存不下就再加一个存储单元)
前面的FFFE是什么?
BOM(Byte Order Mark)
UTF-8 | EF BB BF
UTF-16LE | FF FE
UTF-16BE | FE FF
用来表示是以什么格式来存储Unicode编码字符
UTF-8(变长存储方式)
既然已经有了UTF-16那为什么还要加一个UTF-8呢?
那是因为在网络传输中,原本一个字节就能表示的编码,使用UTF-16后,需要2个字节来表示,极大的降低了网格的传输速率
(如果一个字节能够存储那就使用1个字节,如果两个字节能存储就2个字节来存储,不行就3个字节…)
优点: 节省空间
缺点: 解析麻烦
解析方式
Unicode编码(16进制) UTF-8二进制编码
000000 - 00007F | 0xxxxxxxx
000080 - 0007FF | 110xxxxx 10xxxxxx
000800 - 007FFF | 1110xxxx 10xxxxxx 10xxxxxx
001000 - 10FFFF | 11110xxx 10xxxxxx 10xxxxxx
我们来解析一下上面的A文,可以看到”A“在编码表中为0x41,在000000 - 00007F这个范围中,所以采用直接编码的方式,存储为1个字节,再来看下“文”,在编码表中的范围在000800 - 007FFF这个范围中,所以编码为0xE69687
我们把0x8796E6转为二进制看下是不是按上面的范围来解析的
1110
(0110) 10
(01 0110) 10
(00 0111) => 1110xxxx 10xxxxxx 10xxxxxx
真正有效的是括号里括起来的
011001 011000 0111 转为十六进制后为:0x6578 ,大家可以回到上面看下utf-16下,文在utf-16下的十六进制是什么,正是0x6578(这个0x6578就是在Unicode,utf-16编码下的唯一编码)