字符集和编码方式

字符集

常用字符集分类

ASCII及其扩展字符集
作用:表语英语及西欧语言。
位数:ASCII是用7位表示的,能表示128个字符;其扩展使用8位表示,表示256个字符。
范围:ASCII从00到7F,扩展从00到FF。

ISO-8859-1字符集 —— 又称 Latin-1
作用:扩展ASCII,表示西欧、希腊语等。
位数:8位,把ascll的最高
范围:从00到FF,兼容ASCII字符集。

GB2312字符集
作用:国家简体中文字符集,兼容ASCII。
位数:使用2个字节表示,能表示7445个符号,包括6763个汉字,几乎覆盖所有高频率汉字。
范围:高字节从A1到F7, 低字节从A1到FE。将高字节和低字节分别加上0XA0即可得到编码。

GBK字符集
作用:它是GB2312的扩展,加入对繁体字的支持,兼容GB2312。
位数:使用2个字节表示,可表示21886个字符。
范围:高字节从81到FE,低字节从40到FE。

UCS字符集
作用:国际标准 ISO 10646 定义了通用字符集 (Universal Character Set)。它是与UNICODE同类的组织,UCS-2和UNICODE兼容。
位数:它有UCS-2和UCS-4两种格式,分别是2字节和4字节。
范围:目前,UCS-4只是在UCS-2前面加了0×0000。

UNICODE字符集
作用:为世界650种语言进行统一编码,兼容ISO-8859-1。
位数:UNICODE字符集有多个编码方式,分别是UTF-8,UTF-16和UTF-32。

编码方式

字符集和编码方式是两个不同的概念,字符集可以看做是一个数字和一个特定形状的字符的映射的关系。而编码方式是将一个字符的Unicode编码转换为二进制的形式。
utf-8编码方式是使用最广泛的一种编码方式,它是一种动态字节长度的编码方式,将字符集中字符全部进行编码和解码,并且可以根据字符编号对应的大小来改变编码后的字节长度。比如一个"a" 字符在字符集中的编号为97,编码成二进制只需要一个字节长度即可完成,没有必要使用多个字符。


常见的字符编码方式

UTF-8的编码规则
1)对于单字节的符号,字节的第一位设为0,后面7位为这个符号的unicode码。因此对于英语字母,UTF-8编码和ASCII码是相同的。
2)对于N字节的符号,第一个字节的前N位都设为1,第N+1位为0,后面字节的前两位一律设为10。剩下的二进制位,全部为这个符号的unicode码。

Unicode符号范围 UTF-8编码方式
(十六进制) (二进制)
0000 0000-0000 007F 110xxxxx 10xxxxxx
0000 0080-0000 07FF 110xxxxx 10xxxxxx
0000 0800-0000 FFFF 1110xxxx 10xxxxxx 10xxxxxx
0001 0000-0010 FFFF 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx

如果一个字节的第一位是0,则这个字节单独就是一个字符;如果第一位是1,则连续有多少个1,就表示当前字符占用多少个字节。


由于UTF-8这种节省空间的特性,导致它成为互联网上最常见的网页编码。
比如中文'严'字,二进制表示成:11100100 10111000 10100101
对应的Unicode code point为 0100 1110 0010 0101对应的HEX值x4E25

字节和字符的区别

字节(octet)是一个八位的存储单元,取值范围一定是0~255。而字符(character,或者word)为语言意义上的符号,范围就不一定了。例如在UCS-2中定义的字符范围为0~65535,它的一个字符占用两个字节。

Big Endian和Little Endian
上面提到了一个字符可能占用多个字节,那么这多个字节在计算机中如何存储呢?比如字符0xabcd,它的存储格式到底是 AB CD,还是 CD AB 呢?
实际上两者都有可能,并分别有不同的名字。如果存储为 AB CD,则称为Big Endian;如果存储为 CD AB,则称为Little Endian。
具体来说,以下这种存储格式为Big Endian(大端模式),因为值(0xabcd)的高位(0xab)存储在前面:
地址 值

地址

0x00000000

AB

0x00000001

CD


相反,以下这种存储格式为Little Endian(小端模式):

地址

0x00000000

CD

0x00000001

AB

UCS-2和UCS-4

Unicode是为整合全世界的所有语言文字而诞生的。任何文字在Unicode中都对应一个值,这个值称为代码点(code point)。代码点的值通常写成 U+ABCD 的格式。而文字和代码点之间的对应关系就是UCS-2(Universal Character Set coded in 2 octets)。顾名思义,UCS-2是用两个字节来表示代码点,其取值范围为 U+0000~U+FFFF。可以储存的字符就为65535个

为了能表示更多的文字,人们又提出了UCS-4,即用四个字节表示代码点。它的范围为 U+00000000~U+7FFFFFFF,其中 U+00000000~U+0000FFFF和UCS-2是一样的。要注意,UCS-2和UCS-4只规定了代码点和文字之间的对应关系,并没有规定代码点在计算机中如何存储。规定存储方式的称为UTF(Unicode Transformation Format),其中应用较多的就是UTF-16和UTF-8了。

UTF-16


UTF-16由RFC2781规定,它使用两个字节来表示一个代码点。
UTF-16是完全对应于UCS-2的,即把UCS-2规定的代码点通过Big Endian或Little Endian方式直接保存下来。UTF-16包括三种:UTF-16,UTF-16BE(Big Endian),UTF-16LE(Little Endian)。
UTF-16BE和UTF-16LE不难理解,而UTF-16就需要通过在文件开头以名为BOM(Byte Order Mark:字节序标识)的字符来表明文件是Big Endian还是Little Endian。BOM为U+FEFF这个字符。
其实BOM是个小聪明的想法。由于UCS-2没有定义U+FFFE,因此只要出现 FF FE 或者 FE FF 这样的字节序列,就可以认为它是U+FEFF,并且可以判断出是Big Endian还是Little Endian。
举个例子。“ABC”这三个字符用各种方式编码后的结果如下:

UTF-16BE

00 41 00 42 00 43

UTF-16LE

41 00 42 00 43 00

UTF-16(Big Endian)

FE FF 00 41 00 42 00 43

UTF-16(Little Endian)

FF FE 41 00 42 00 43 00

UTF-16(不带BOM)

00 41 00 42 00 43


Windows平台下默认的Unicode编码为Little Endian的UTF-16

另外,UTF-16还能表示一部分的UCS-4代码点——U+10000~U+10FFFF。UCS-2中的 U+D800~U+DFFF 变成了无定义的字符。

UTF-32


UTF-32用四个字节表示代码点,这样就可以完全表示UCS-4的所有代码点。与UTF-16类似,UTF-32也包括UTF-32、UTF-32BE、UTF-32LE三种编码,UTF-32也同样需要BOM字符。仅用'ABC'举例:

UTF-32BE

00 00 00 41 00 00 00 42 00 00 00 43

UTF-32LE

41 00 00 00 42 00 00 00 43 00 00 00

UTF-32(Big Endian)

00 00 FE FF 00 00 00 41 00 00 00 42 00 00 00 43

UTF-32(Little Endian)

FF FE 00 00 41 00 00 00 42 00 00 00 43 00 00 00

UTF-32(不带BOM)

00 00 00 41 00 00 00 42 00 00 00 43

UTF-8

UTF-16和UTF-32的一个缺点就是它们固定使用两个或四个字节,这样在表示纯ASCII文件时会有很多00字节,造成浪费。而RFC3629定义的UTF-8则解决了这个问题。
UTF-8用1~4个字节来表示代码点。表示方式如下:

UCS-2 (UCS-4)

位序列

第一字节

第二字节

第三字节

第四字节

U+0000 .. U+007F

00000000-0xxxxxxx

0xxxxxxx

 

 

 

U+0080 .. U+07FF

00000xxx-xxyyyyyy

110xxxxx

10yyyyyy

 

 

U+0800 .. U+FFFF

xxxxyyyy-yyzzzzzz

1110xxxx

10yyyyyy

10zzzzzz

 

U+10000..U+10FFFF

00000000-000wwwxx-

xxxxyyyy-yyzzzzzzz

11110www

10xxxxxx

10yyyyyy

10zzzzzz

​​
可见,ASCII字符(U+0000~U+007F)部分完全使用一个字节,避免了存储空间的浪费。而且UTF-8不再需要BOM字节。
另外,从上表中可以看出,单字节编码的第一字节为[00-7F],双字节编码的第一字节为[C2-DF],三字节编码的第一字节为[E0-EF]。这样只要看到第一个字节的范围就可以知道编码的字节数。这样也可以大大简化算法。

原文地址:https://www.cnblogs.com/k5210202/p/13068462.html