白衣苍狗

天上浮云似白衣,斯须改变如苍狗

0%

字符编码

简单记录下字符编码的一些细节,省去以后总是查资料的麻烦

ASCII

最基本的一种字符编码。每个字符占用一个字节,编码范围为0x00-0x7F,其中0x00-0x1F, 0x7F为33个控制字符,不实际显示,0x20-0x7E共95个可显示字符。
编码如下[1]

控制字符

二进制 十进制 十六进制 缩写 Unicode
表示法
脱出字符
表示法
名称/意义
0000 0000 0 00 NUL ^@ 空字符(Null)
0000 0001 1 01 SOH ^A 标题开始
0000 0010 2 02 STX ^B 本文开始
0000 0011 3 03 ETX ^C 本文结束
0000 0100 4 04 EOT ^D 传输结束
0000 0101 5 05 ENQ ^E 请求
0000 0110 6 06 ACK ^F 确认回应
0000 0111 7 07 BEL ^G 响铃
0000 1000 8 08 BS ^H 退格
0000 1001 9 09 HT ^I 水平定位符号
0000 1010 10 0A LF ^J 换行键
0000 1011 11 0B VT ^K 垂直定位符号
0000 1100 12 0C FF ^L 换页键
0000 1101 13 0D CR ^M CR (字符)
0000 1110 14 0E SO ^N 取消变换(Shift out)
0000 1111 15 0F SI ^O 启用变换(Shift in)
0001 0000 16 10 DLE ^P 跳出数据通讯
0001 0001 17 11 DC1 ^Q 设备控制一(XON 激活软件速度控制)
0001 0010 18 12 DC2 ^R 设备控制二
0001 0011 19 13 DC3 ^S 设备控制三(XOFF 停用软件速度控制)
0001 0100 20 14 DC4 ^T 设备控制四
0001 0101 21 15 NAK ^U 确认失败回应
0001 0110 22 16 SYN ^V 同步用暂停
0001 0111 23 17 ETB ^W 区块传输结束
0001 1000 24 18 CAN ^X 取消
0001 1001 25 19 EM ^Y 连线介质中断
0001 1010 26 1A SUB ^Z 替换
0001 1011 27 1B ESC ^[ 退出键
0001 1100 28 1C FS ^\ 文件分割符
0001 1101 29 1D GS ^] 组群分隔符
0001 1110 30 1E RS ^^ 记录分隔符
0001 1111 31 1F US ^_ 单元分隔符
0111 1111 127 7F DEL ^? Delete字符

可显示字符

二进制 十进制 十六进制 图形
0010 0000 32 20 (space)
0010 0001 33 21 !
0010 0010 34 22
0010 0011 35 23 #
0010 0100 36 24 $
0010 0101 37 25 %
0010 0110 38 26 &
0010 0111 39 27
0010 1000 40 28 (
0010 1001 41 29 )
0010 1010 42 2A *
0010 1011 43 2B +
0010 1100 44 2C ,
0010 1101 45 2D -
0010 1110 46 2E .
0010 1111 47 2F /
0011 1010 58 3A :
0011 1011 59 3B ;
0011 1100 60 3C <
0011 1101 61 3D =
0011 1110 62 3E >
0011 1111 63 3F ?
0100 0000 64 40 @
0101 1011 91 5B [
0101 1100 92 5C \
0101 1101 93 5D ]
0101 1110 94 5E ^
0101 1111 95 5F _
0110 0000 96 60 `
0111 1011 123 7B {
0111 1100 124 7C \
0111 1101 125 7D }
0111 1110 126 7E ~
  • 0x30-0x39为数字0-9
  • 0x41-0x5A为大写字母A-Z
  • 0x61-0x7A为小写字母a-z

Unicode

Unicode,联盟官方中文名称为统一码,是计算机科学领域的业界标准。它整理、编码了世界上大部分的文字系统,使得电脑可以用更为简单的方式来呈现和处理文字。[2]

Unicode基本上可以理解为为了将人类所有文字(表情)都进行编码,目前也基本编码了大多数文字,在很大程度上解决了计算机中的编码问题。2021年9月发布了Unicode 14.0

编码方式

基本的Unicode字符使用2字节编码一个字符,因此理论上可以表示216即65526个字符,不过实际上并未用完这个65526个位置。但是另一方面即使是中文字符也不止6万个字符,因此还引入了辅助平面的概念,基本上可以理解为分为了不同的组。

目前总共有0(基本平面),1-16(辅助平面)总共17个平面,这样总共可以表示超过100万个字符,对于人类来说妥妥够用了。实际上辅助平面现在利用上的也才几个。虽然只有16个辅助平面,但是辅助平面的Unicode字符会占用4个字节,这是为了和UCS-4保持一致的原因

基本平面的字符编码格式为U+hhhh,每个h代表一个16进制数,即用4位16进制数表示。辅助平面的字符会在之前加上一个一位表示平面数的数,如第一辅助平面的字符编码为U+10000~U+1FFFF

基本多文种平面(BMP)

  • 基本平面中U+0000~U+007F与ASCII一致
  • U+D800~U+DFFF中不存在任何字符

辅助平面

平面 范围 用途 简称
1号平面 U+10000 - U+1FFFF 多文种补充平面 Supplementary Multilingual Plane,简称SMP
2号平面 U+20000 - U+2FFFF 表意文字补充平面 Supplementary Ideographic Plane,简称SIP
3号平面 U+30000 - U+3FFFF 表意文字第三平面 Tertiary Ideographic Plane,简称TIP
4号平面至13号平面 U+40000 - U+DFFFF (尚未使用)
14号平面 U+E0000 - U+EFFFF 特别用途补充平面 Supplementary Special-purpose Plane,简称SSP
15号平面 U+F0000 - U+FFFFF 保留作为私人使用区(A区) Private Use Area-A,简称PUA-A
16号平面 U+100000 - U+10FFFF 保留作为私人使用区(B区) Private Use Area-B,简称PUA-B

UTF-8

从Unicode的编码方式可以看出,基本平面的字符不管啥都要使用两个字节编码,这对于英文字符来说是极大的空间浪费,因此有了可变长度字符编码。这种编码方式还是非常有意思的。

UTF-8是UNICODE的一种变长度的编码表达方式,一般UNICODE为双字节(指UCS2),它由肯·汤普逊(Ken Thompson)于1992年创建,现在已经标准化为RFC 3629。UTF-8就是以8位为单元对UCS进行编码,而UTF-8不使用大尾序和小尾序的形式,每个使用UTF-8存储的字符,除了第一个字节外,其余字节的头两个比特都是以”10”开始,使文字处理器能够较快地找出每个字符的开始位置。[3]

编码结构

目前来说,UTF-8使用一至四个字节为每个字符编码(理论上最大可以使用六个字节):

  • 128个US-ASCII字符只需一个字节编码(Unicode范围由U+0000至U+007F)
  • 带有附加符号的拉丁文、希腊文、西里尔字母、亚美尼亚语、希伯来文、阿拉伯文、叙利亚文及它拿字母则需要两个字节编码(Unicode范围由U+0080至U+07FF)。
  • 其他基本多文种平面(BMP)中的字符(这包含了大部分常用字,如大部分的汉字)使用三个字节编码(Unicode范围由U+0800至U+FFFF)。
  • 其他极少使用的Unicode 辅助平面的字符使用四至六字节编码(Unicode范围由U+10000至U+1FFFFF使用四字节,Unicode范围由U+200000至U+3FFFFFF使用五字节,Unicode范围由U+4000000至U+7FFFFFFF使用六字节)。

比特分配方式

代码范围
十六进制
标量值(scalar value)
二进制
UTF-8
二进制/十六进制
注释
000000~00007F
128个代码
00000000 00000000 0zzzzzzz
七个z
0zzzzzzz(00-7F)
七个z
ASCII字符范围,字节由零开始
000080~0007FF
1920个代码
00000000 00000yyy yyzzzzzz
三个y;二个y;六个z
110yyyyy(C0-DF) 10zzzzzz(80-BF)
五个y;六个z
第一个字节由110开始,接着的字节由10开始
000800~00D7FF
00E000~00FFFF
61440个代码
00000000 xxxxyyyy yyzzzzzz
四个x;四个y;二个y;六个z
1110xxxx(E0-EF) 10yyyyyy 10zzzzzz
四个x;六个y;六个z
第一个字节由1110开始,接着的字节由10开始
010000~10FFFF
1048576个代码
000wwwxx xxxxyyyy yyzzzzzz 11110www(F0-F7)
三个w;二个x;四个x;四个y;二个y;六个z
10xxxxxx 10yyyyyy 10zzzzzz
三个w;六个x;六个y;六个z
将由11110开始,接着的字节由10开始

从Unicode码转换为UTF-8编码的流程基本为:

  1. 根据Unicode码所处的范围确定需要用几个字节,如字母A处于U+0000~U+007F的范围,那么就使用一个字符编码
  2. 将该字符Unicode码用二进制表示(上表第二行),根据UTF-8每字节要求将其分割,其中z表示属于UTF-8中第一个字节(大端序),y属于第二个字节,x属于第三个字节,w属于第四个字节
  3. UTF-8根据每个字节开头的1的个数确定该字节属于整体的第几个字节。如果开头为0则整个字符只有一个字节。
  4. 将每个比特填入对于的字节即可。

一二三四五六七八九十为例

1
2
3
  Offset: 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 
00000000: E4 B8 80 E4 BA 8C E4 B8 89 E5 9B 9B E4 BA 94 E5
00000010: 85 AD E4 B8 83 E5 85 AB E4 B9 9D E5 8D 81

共30bytes。

UTF-8到Unicode的转换则反过来,根据占用了几个字符确定该字符属于哪个范围,从每个字节中取出有效位数组合成完整的Unicode码

UTF-8编码的中文字符,若在基本平面则都需要3个字符,若在辅助平面则需要4个字符

从UTF-8的编码规则可以看出,诸如110yyyyy 0zzzzzzz这样的数据将是非法的数据。

上表的编码规则可以很轻松的扩展到6个字节,当然这也是UTF-8可以编码的上限了(虽然有生之年应该用不上的了)

UTF-16

日后再补

UTF-16也是Unicode的一种编码方式,基本平面字符使用2字节,扩展平面字符使用4字节。[4]

编码结构

  • 基础平面的Unicode字符的UTF-16编码就是对应的Unicode码的16进制形式
  • 扩展平面的字符以后再说。

大尾序/小尾序与BOM

1
2
3
  Offset: 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
00000000: FF FE 00 4E 8C 4E 09 4E DB 56 94 4E 6D 51 03 4E
00000010: 6B 51 5D 4E 41 53

共22bytes。

GB 2312

GB/T 2312[注 1],GB/T 2312–80 或 GB/T 2312–1980 是中华人民共和国国家标准简体中文字符集,全称《信息交换用汉字编码字符集·基本集》,通常简称GB(“国标”汉语拼音首字母),又称GB0,由中国国家标准总局于1980年发布,1981年5月1日实施。GB/T 2312编码通行于中国大陆;新加坡等地也采用此编码。中国大陆几乎所有的中文系统和国际化的软件都支持GB/T 2312。[5]

GB/T 2312标准共收录6763个汉字,其中一级汉字3755个,二级汉字3008个;同时收录了包括拉丁字母、希腊字母、日文平假名及片假名字母、俄语西里尔字母在内的682个字符。

这也就意味着只支持常用汉字,很多生僻字是没有收录的

编码结构

GB/T 2312中对所收汉字进行了“分区”处理,每区含有94个汉字/符号,共计94个区。用所在的区和位来表示字符(实际上就是码位),因此称为区位码(或许叫“区位号”更为恰当)。表示方式也称为区位码。例如“万”字在45区82位,所以“万”字的区位码是:45 82(注意,GB类汉字编码为双字节编码,因此,45相当于高位字节,82相当于低位字节)。

01~09区(682个):特殊符号、数字、英文字符、制表符等,包括拉丁字母、希腊字母、日文平假名及片假名字母、俄语西里尔字母等在内的682个全角字符;
10~15区:空区,留待扩展;在附录3,第10区推荐作为 GB 1988–80 中的94个图形字符区域(即第3区字符之半形版本)。
16~55区(3755个):常用汉字(也称一级汉字),按拼音排序;
56~87区(3008个):非常用汉字(也称二级汉字),按部首/笔画排序;
88~94区:空区,留待扩展。

1
2
3
  Offset: 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
00000000: D2 BB B6 FE C8 FD CB C4 CE E5 C1 F9 C6 DF B0 CB
00000010: BE C5 CA AE

共20bytes。

GBK

https://zh.wikipedia.org/wiki/%E6%B1%89%E5%AD%97%E5%86%85%E7%A0%81%E6%89%A9%E5%B1%95%E8%A7%84%E8%8C%83

GB 18030

https://zh.wikipedia.org/wiki/GB_18030

Big5

https://zh.wikipedia.org/wiki/%E5%A4%A7%E4%BA%94%E7%A2%BC

宽字符

https://zh.wikipedia.org/wiki/%E5%AF%AC%E5%AD%97%E5%85%83

代码页

https://zh.wikipedia.org/wiki/%E4%BB%A3%E7%A0%81%E9%A1%B5

UCS2

半角和全角

https://zh.wikipedia.org/wiki/%E5%85%A8%E5%BD%A2%E5%92%8C%E5%8D%8A%E5%BD%A2

http://www.ruanyifeng.com/blog/2007/10/ascii_unicode_and_utf-8.html


  1. 1.https://zh.wikipedia.org/wiki/ASCII
  2. 2.https://zh.wikipedia.org/wiki/Unicode
  3. 3.https://zh.wikipedia.org/wiki/UTF-8#UTF-8%E7%BC%96%E7%A0%81%E5%AD%97%E8%8A%82%E5%90%AB%E4%B9%89
  4. 4.https://zh.wikipedia.org/wiki/UTF-16
  5. 5.https://zh.wikipedia.org/wiki/GB_2312