unicode编码 中文unicode编码查询
一,发文目的
理解常用的字符编码,不至于看到之后一脸懵逼。
二、文章大纲
1,ASCII码
2,区位码
3,GB2312码
4,UCS-2码,UCS-4码
5,UTF-16码,UTF-32码
6,UTF-8码
7,什么是BOM
8,什么是大端和小端
三、正文内容
1,ASCII码
ASCII(American Standard Code for Information Interchange,美国信息交换标准代码),使用一个字节来表示一个字符,一个字节8位,一共可以表示2^8=256个字符。
2,区位码
在GB2312—1980中将全部国标汉字及符号组成一个94×94的矩阵。每一行称为一个“区”,每一列称为一个“位”,于是构成了一个有94个区(01~94区),每个区有94个位(01~94位)的汉字字符集。区码与位码组合在一起就形成了“区位码”,唯一地确定某一汉字或符号。例如“我”的区位码是4650,注意区位码是十进制数组成的。
3,GB2312码
即汉字在内存里面的表现形式,以上提到了区位码,区位码只是汉字的编码表,用十进制数来表示方便查找,但是在机器内部,并不是以区位码来存储,为了不与ASCII码发生冲突,所以于是在区位码前后两个字节上再加上0xA0,这样就由区位码得到了可以用于存储在计算机内部的GB2312编码。例如“我”的区位码是4650,转换为十进制表示0x2E32,前后两个字节分别加上0xA0之后,变成0xCED2,即GB2312码,汉字“我”内存中的表示为0XCED2
4,UCS-2,UCS-4码
为了统一所有的编码,ISO制定了“通用字符集”(Universal Character Set,简称UCS),将世界上所有的字符编成一张表,就是unicode表,unicode将字符按照一定的类别划分为0?16这17个页中,每个也拥有2^16 = 65536个字符,常用的字符在第一页,称为第一个平面称为基本多语言平面(Basic Multilingual Plane, BMP)。BMP内,从D800到U+DFFF之间的码位是永久保留的,不代表任何字符。unicode中,汉字“我”的码位是0x6211
UCS-2,UCS-4只是两种编码格式,对“通用字符集”中的字符进行编码。
UCS-2意思是用2个字节来表示一个字符,这样可以表示2^16=65536个字符,0xD800-0xDFFF之间的码位未使用。字符的编码就是unicode中的码的值;例如“我”的UCS-2码就是0x6211
UCS-4意思是用4个字节来表示一个字符,最高位为0,,这样编码空间为0x00000000?0x7FFFFFFF(可以编码20多亿个字符),虽然UCS-4有20多亿个编码空间,但实际使用范围并不超过0x10FFFF。在不超过0x10FFFF范围内的字符,UCS-4码的值也就是unicode中的码元的值,比如“我”的UCS-4码就是0x00006211
5,UTF-16码
UTF-16,与UCS-2一样,它使用两个字节为BMP页中的字符编码;它使用4个字节对BMP外的字符进行编码。
当字符在范围:0x0000?0xD7FF以及0xE000?0xFFFF时:UTF-16码的数值等价于对应的码位
当字符在范围:0x10000?0x10FFFF时:字符被编码为一对16比特长的码元,称作代理对(surrogate pair)
此时,UTF-16码占用4个字节表示,分为高2个字节的代理和低2个字节的代理值,具体方法是:
- 码位减去0x10000,得到的值的范围为0x0?0xFFFFF,共占20位
- 将高位的10bit的值,0x0?0x3FF,加上0xD800得到高2个字节的代理值。
- 将低位的10bit的值,0x0?0x3FF,加上0xDC00得到低2个字节的代理值。
UTF-32码,与UCS-4一样,采用4个字节来表示一个字符。只不过其编码空间被限定在了0?0x10FFFF之间。因此也可以说:UTF-32是UCS-4的一个子集。
6,UTF-8码
以上UTF-16/UCS-2或者UTF-32/UCS-4,缺点在于不够灵活,表示常规的字符时,空间利用率不高。
UTF-8的编码格式:
在UTF-8编码中,ASCII码中的字符还是ASCII码的值,只需要一个字节表示,其余的字符需要2字节、3字节或4字节来表示。
UTF-8的编码规则很简单,只有二条:
1)对于ASCII码(0x0?0x7F)该字节的最高位(Bit7)设为0,后面剩余的7位为这个符号的unicode码(ASCII码)。
例如“|”的ASCII码是0x7C,那么它的UTF-8码也是一个字节0x7C
因此对于英语字母,UTF-8编码和ASCII码是相同的。
对于ASCII码的高位部分(0x80?0xFF),需要用两个字节来表示它的UTF-8编码。
例如“¥”的ASCII码是0xA5,那么它的UTF-8编码就是0xC2A5,具体换算见下面
2)对于2,3,4,5...n个字节的符号,高位字节的前n位都设为1,第n+1位设为0,后面剩余字节的前两位一律设为10。剩下的二进制位,全部为这个符号的unicode码。
比如“¥”的ASCII码是0xA5,即 1010 0101
本身字符的码元占1个字节,因为UTF-8的编码中含有一些特别的标志位,因此编码后的UTF-8得占用2个字节表示。
又因为首字节的高位连续的1代表几个字节,既然这里需要用2个字节,于是首字节的高位是两个1,后面还有一个0;剩余的字节前面以10开头,这样框架就是110X_XXXX 10XX_XXXX
下面将“¥”的二进制位1010 0101填充进去,就得到1100_0010 1010_0101,即0xC2A5
7,什么是BOM
windows的记事本,另存为时,可选的编码有四种:
ANSI,Unicode,Unicode big endian,UTF-8 四种编码方式
所谓ANSI, 其实是 Windows code pages,这个模式根据当前 locale 选定具体的编码, 对于简体中文文件是GB2312编码,如果是繁体中文版会采用 Big5 码。也就是说,对于不同的语言版本的安装系统,选用默认的字体编码。
所谓Unicode,是指 带有 BOM 的小端顺序的 UTF-16 编码;
所谓Unicode big endian,是指带有BOM的大端顺序的UTF-16编码;
所谓UTF-8,是指带BOM的UTF-8编码(大端顺序存储);
BOM是指Byte Order Mark,字节顺序标志。是在Windows系统中对于字符的编码的一种规范。如果是UTF-16/UCS-2的小端存储,则BOM是FFFE;如果是UTF-16/UCS-2的大端存储,则BOM是FEFF;如果是UTF-8存储,则BOM是EFBBBF
因为已经知道了UTF-8的编码规则,那么EFBBBF是什么的UTF-8编码?
EFBBBF二进制是 1110_1111,1011_1011,1011_1111,可以发现第一个字节的高位是1110,说明编码占3个字节,第二个字节和第三个字节的高位是以10开头,符合规范,那么EFBBBF所代表的字符的unicode码元是1111,1110,1111_1111,即0xFEFF,即大端存储。
即在Windows内,UTF-8编码是指用大端BOM方式存储utf-8编码。
8,什么是大端和小端
对于多个字节的情况,这些字节在内存地址中是如何存放的,有两种情况:一种是高字节放在高地址中,低字节放在低地址中。这种情况叫做小端;
另一种情况相反,高字节放在低地址中,低字节放在高地址中,这种情况叫做小端。
(以上排序,都是以字节为最小单位,字节作为一个整体,字节内的位不再区分高低进行放置)
utf-8是以大端方式存储的。
大端,英文名“Big-endian”;小端(BE),英文名“Little-endian”(LE)因此看到类似这样的编码:
UCS-2 BE,UCS-2 LE 就应该知道这代表什么意思。
一个程序来判断你的计算机是小端还是大端。
我的电脑,intel处理器,小端模式