简单记录下字符编码的一些细节,省去以后总是查资料的麻烦
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-90x41-0x5A为大写字母A-Z0x61-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编码的流程基本为:
- 根据Unicode码所处的范围确定需要用几个字节,如字母
A处于U+0000~U+007F的范围,那么就使用一个字符编码 - 将该字符Unicode码用二进制表示(上表第二行),根据UTF-8每字节要求将其分割,其中
z表示属于UTF-8中第一个字节(大端序),y属于第二个字节,x属于第三个字节,w属于第四个字节 - UTF-8根据每个字节开头的
1的个数确定该字节属于整体的第几个字节。如果开头为0则整个字符只有一个字节。 - 将每个比特填入对于的字节即可。
例
以一二三四五六七八九十为例
1 | Offset: 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F |
共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 | Offset: 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F |
共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 | Offset: 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F |
共20bytes。
GBK
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