编码

# 编码

* 演变史:https://www.zhihu.com/question/23374078
* 中国人民通过对 ASCII 编码的中文扩充改造,产生了 GB2312 编码,可以表示6000多个常用汉字。
* 汉字实在是太多了,包括繁体和各种字符,于是产生了 GBK 编码,它包括了 GB2312 中的编码,同时扩充了很多。
* 中国是个多民族国家,各个民族几乎都有自己独立的语言系统,为了表示那些字符,继续把 GBK 编码扩充为 GB18030 编码。
* 每个国家都像中国一样,把自己的语言编码,于是出现了各种各样的编码,如果你不安装相应的编码,就无法解释相应编码想表达的内容。
* 终于,有个叫 ISO 的组织看不下去了。他们一起创造了一种编码 UNICODE(直接规定必须用两个字节,也就是16位来统一表示所有的字符) ,这种编码非常大,大到可以容纳世界上任何一个文字和标志。所以只要电脑上有 UNICODE 这种编码系统,无论是全球哪种文字,只需要保存文件的时候,保存成 UNICODE 编码就可以被其他电脑正常解释。
* UNICODE 在网络传输中,出现了两个标准 UTF-8 和 UTF-16,分别每次传输 8个位和 16个位。于是就会有人产生疑问,UTF-8 既然能保存那么多文字、符号,为什么国内还有这么多使用 GBK 等编码的人?因为 UTF-8 等编码体积比较大,占电脑空间比较多,如果面向的使用人群绝大部分都是中国人,用 GBK 等编码也可以。

### ASCii

* 前127位
* 0~31及127(共33个)是控制字符或通信专用字符(其余为可显示字符)
* 32~126(共95个)为阿拉伯数字,大小写英文字母,标点符号,运算符号
* 后128个称为扩展ASCII码。许多基于x86的系统都支持使用扩展(或“高”)ASCII。扩展ASCII 码允许将每个字符的第8 位用于确定附加的128 个特殊符号字符、外来语字母和图形符号。


---
https://baike.baidu.com/item/Unicode#3
### Unicode

* 目前的Unicode字符分为17组编排,0x0000至0x10FFFF,每组称为平面(Plane),而每平面拥有65536个码位,共1114112个
* UCS
* 通用字符集(Universal Character Set, UCS)是由ISO制定标准字符集
* UCS-4根据最高位为0的最高字节分成27=128个组(group)。每个group再根据次高字节分为256个平面(plane)。每个平面根据第3个字节分为256行 (row),每行有256个码位(cell)
* 如果UCS-4的前两个字节为全零,那么将UCS-4的BMP去掉前面的两个零字节就得到了UCS-2
* Unicode计划使用了17个平面,一共有17×65536=1114112个码位
* UTF
* Unicode Transformation Format,可以翻译成Unicode字符集转换格式,即怎样将Unicode定义的数字转换成程序数据
* “汉字”对应的数字是0x6c49和0x5b57,而编码的程序数据是

```
char data_utf8[]={0xE6,0xB1,0x89,0xE5,0xAD,0x97};//UTF-8编码,6个字节
char16_t data_utf16[]={0x6C49,0x5B57}; //UTF-16编码,需要两个char16_t,4个字节
char32_t data_utf32[]={0x00006C49,0x00005B57};//UTF-32编码,需要两个char32_t,8个字节
```

* UTF-8
* 以字节为单位对Unicode进行编码
* 它是一种变长的编码方式。它可以使用1~4个字节表示一个符号,根据不同的符号而变化字节长度
* 当字符在ASCII码的范围时,就用一个字节表示,保留了ASCII字符一个字节的编码做为它的一部分
* 注意的是unicode一个中文字符占2个字节,而UTF-8一个中文字符占3个字节)
* 从unicode到utf-8并不是直接的对应,而是要过一些算法和规则来转换。

* UTF-16
* UTF-16编码以16位无符号整数为单位。
* 我们把Unicode编码记作U。编码规则如下:
* 如果U<0x10000,则U的UTF-16编码就是U对应的16位无符号整数(为书写简便,下文将16位无符号整数记作WORD)。
* 如果U≥0x10000,我们先计算U'=U-0x10000,然后将U'写成二进制形式:yyyy yyyy yyxx xxxx xxxx,U的UTF-16编码(二进制)就是:110110yyyyyyyyyy 110111xxxxxxxxxx。
* UTF-16比起UTF-8,好处在于大部分字符都以固定长度的字节(2字节)储存,但UTF-16却无法兼容于ASCII编码

* 总结
* unicode是字符集,对字符集数字化;
* utf8是编码方式,为更好的存储和传输。
* unicode一个中文字符占2个字节,而UTF-8一个中文字符占3个字节
* 在 Java 中, char 类型用 UTF-16 编码描述一个代码单元。
```
”汉”的unicode值是0x6C49,转化为2进制 1101100 01001001
字符集编码是UTF-8:”汉”字在计算机内部保存的值为0xE6B189,也就是11100110 10110001 10001001,可以看到”汉”字变成了3个字节
UTF-16只能是选两字节或四字节来保存字符,那么”汉”字仍为仍为0x6C49,也就是 1101100 01001001
而UTF-32就是把所有的字符都用32bit也就是4个字节来表示
```
* 注意:unicode的一段历史
* 首先要注意unicode并不是用2个字节来表示字符串的。unicode1.0版本,所有的字符都是2个字节。但是现在的unicode编码在一百一十万左右,远远超过了2的16次方,也就是2个字节。所以,现在讲unicode编码是2个字节是错误的!
* Unicode 编码共有三种具体实现,分别为utf-8,utf-16,utf-32,其中utf-8占用一到四个字节,utf-16占用二或四个字节,utf-32占用四个字节

上一篇:windows 驱动开发- 内核中字符串数据结构


下一篇:解决python2查询后各种unicode的问题