w字符编码
字符编码
- 前言
- 一、字符,字符集,字符编码方式的区别
- 二、字符集
- 三、字符编码(UTF8,UTF16,UTF32)
- UTF-32
- UTF16
- UTF8
- 四、字符序
- Big-Endian和Little-Endian
- 编码识别
前言
经常遇到一些编码方面的问题绕来绕去的,决定好好学习记录一下。
一、字符,字符集,字符编码方式的区别
-
字符:字符是抽象的最小文本单位。它没有固定的形状(可能是一个字形),而且没有值。“A”是一个字符,“€”(德国、法国和许多其他欧洲国家通用货币的标志)也是一个字符。“中”“国”这是两个汉字字符。字符仅仅代表一个符号。
-
字符集:也就是某个符号和某个数字映射关系的一个表,也就是它决定了21475 是口碑的“口”,不同的表有不同的映射关系,如 ascii,gb2312,Unicode(注意UTF-8不是字符集). 通过这个数字和字符的映射表,我们可以把一个二进制表示的数字转换成某个字符。
-
字符编码方式:例如,同是对于应“口”的 21475 这个数,我们是用 \u5k3e3 表示呢,还是用 %E5%8F%A3 来表示呢?这就是由 character encoding 来决定的。UTF-8指的也就是字符的编码方式了。
二、字符集
Unicode字符集大全
中文字符集的包含关系:
1.ASCII及其扩展字符集
作用:表语英语及西欧语言。
位数:ASCII是用7位表示的,能表示128个字符;其扩展使用8位表示,表示256个字符。
范围:ASCII从00-7F,扩展从00-FF。
2.ISO-8859-1字符集
作用:扩展ASCII,表示西欧、希腊语等。
位数:8位,
范围:从00-FF,兼容ASCII字符集。
3.GB2312字符集
作用:国家简体中文字符集,兼容ASCII。
位数:使用2个字节表示,能表示7445个符号,包括6763个汉字,几乎覆盖所有高频率汉字。
范围:高字节从A1到F7, 低字节从A1到FE。将高字节和低字节分别加上0XA0即可得到编码。
4.BIG5字符集
作用:统一繁体字编码。
位数:使用2个字节表示,表示13053个汉字。
范围:高字节从A1到F9,低字节从40到7E,A1到FE。
5.GBK字符集
作用:它是GB2312的扩展,加入对繁体字的支持,兼容GB2312。
位数:使用2个字节表示,可表示21886个字符。
范围:高字节从81到FE,低字节从40到FE。
6.GB18030字符集
作用:它解决了中文、日文、朝鲜语等的编码,兼容GBK。
位数:它采用变字节表示(1 ASCII,2,4字节)。可表示27484个文字。
范围:1字节从00到7F; 2字节高字节从81到FE,低字节从40到7E和80到FE;4字节第一三字节从81到FE,第二四字节从30到39。
7.UNICODE字符集
作用:为世界650种语言进行统一编码,兼容ISO-8859-1。
位数:UNICODE字符集有多个编码方式,分别是UTF-8,UTF-16和UTF-32。
范围:0-0x10FFFF映射字符,最多可以容纳1114112个字符。
三、字符编码(UTF8,UTF16,UTF32)
此处的字符编码是针对与Unicode字符集的不同显示方式。
UTF-32
UTF-32 是固定长度的编码,始终占用 4 个字节,足以容纳所有的 Unicode 字符,所以直接存储 Unicode 编号即可,不需要任何编码转换。浪费了空间,提高了效率。
UTF16
最开始是以2个字节也就是16位进行记录。
例如:
字符 | Unicode码数 | Unicode码数16进制 | UTF16表示 |
---|---|---|---|
我 | 25105 | 6211 | 0011 1110 0000 1011 |
但是可以发现一两个字节存储最多也就到0xFFFF(65535)与UNICODE字符集0-0x10FFFF的范围还相差很多,所以就出现了4个字节记录的UTF16编码,其编码规则如下:
Unicode码数范围(16进制) | Unicode码数(2进制) | UTF16表示 | 编码后的字节数 |
---|---|---|---|
0000 - FFFF | XXXX XXXX XXXX XXXX | XXXX XXXX XXXX XXXX | 2 |
0001 0000 - 0010 FFFF | YYYY YYYY YYXX XXXX XXXX | 110110YY YYYYYYYY 110111XX XXXXXXXX | 4 |
明显的以110110来指示高位,以110111来指示低位。
又因为找到高位指示后会默认4字节表示,为不与2个字节记录时产生冲突故,(11011000 00000000 - 1101111111111111)也就是(D800 -DFFF)这个范围就都没有定义,所以对于2个字节存储的UTF16范围就在(0-0xD800 和 0xDFFF-0xFFFF)。
UTF8
由于UTF16存储不能向下兼容Ascii码(原先一个字节就能存储的,UTF16最少也要用两个字节表示,会造成内存浪费的情况)故从制定了可变字节长度(1-4字节)的编码方式UTF8.
编码规则如下:
Unicode码数范围(16进制) | UTF8表示 | 实际编码位 | Unicode码数(2进制) | UTF8编码后的字节数 |
---|---|---|---|---|
0- 7F | 0XXX XXXX | 7 | XXX XXXX | 1 |
80 - 7FF | 110X XXXX 10XX XXXX | 11 | XXX XXXX XXXX | 2 |
800 - FFFF | 1110 XXXX 10XX XXXX 10XX XXXX | 16 | XXXX XXXX XXXX XXXX | 3 |
1 0000 - 1F FFFF | 1111 0XXX 10XX XXXX 10XX XXXX 10XX XXXX | 21 | X XXXX XXXX XXXX XXXX XXXX | 4 |
举例:
字符 | Unicode码数(10进制) | Unicode码数(16进制) | Unicode码数2进制 | UTF8(2进制表示) | UTF8(16进制表示) |
---|---|---|---|---|---|
我 | 25105 | 6211 | 110 0010 0001 0001 | 1110 0110 1000 1000 1001 0001 | E6 88 91 |
四、字符序
但是由于UTF16,UTF32的设计,直接给我们多个字节,我们并不能知道哪个字节是数据高位、哪个字节是数据低位。因此指示字符排列顺序的被称为字符序。
Big-Endian和Little-Endian
Big-Endian(大端模式):就是高位字节排放在内存的低地址端,低位字节排放在内存的高地址端。
若当前内存值为0X12345678
低地址 高地址
----------------------------------------->
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 12 | 34 | 56 | 78 |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Little-Endian(小端模式):就是低位字节排放在内存的低地址端,高位字节排放在内存的高地址端。
低地址 高地址
----------------------------------------->
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 78 | 56 | 34 | 12 |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
例如:
当我在文本中键入”你“字符(Unicode码数(16进制)= 4F60)并选择小端模式时;
可以看出60(低字节位)被放在了前面(低地址端)。
把文本改成大端模式时:
可以看出4F(高字节位)被放在了前面(低地址端)。
编码识别
文件存储中,UNICODE根据前几个字节可以判断UNICODE字符集的各种编码,叫做Byte Order Mask方法BOM:
UTF-8: EF BB BF (符合UTF-8格式。)
UTF-16 Big Endian:FE FF
UTF-16 Little Endian:FF FE
UTF-32 Big Endian:0000 FEFF
UTF-32 Little Endian:FFFE 0000
GB2312:高字节和低字节的第1位都是1。
BIG5,GBK&GB18030:高字节的第1位为1。操作系统有默认的编码,常为GBK,可以下载别的并升级。通过判断高字节的第1位从而知道是ASCII或者汉字编码。