unicode 字符集 与 utf-8 编码

字符集 

Unicode 是一个很大的集合,可以容纳100多万个符号。每个符号的编号都不一样,比如,U+0639表示阿拉伯字母AinU+0041表示英语的大写字母AU+4E25表示汉字。具体的符号编号对应表,可以查询unicode.org,或者专门的汉字对应表

 

字符编码

有了字符集,人们就可以基于其上制定字符与二进制表示(实际上就是数字)的编码规则了。这些规则,就是字符编码。

因为字符集本身就带有一组编号(码位)。因此,字符集本身也能直接用于字符编码。例如,ASCII 既是字符集,也是字符编码;GBK 也是同样。对于这种情况,字符集和字符编码合二为一,没有任何区别。因此,当人们讲「GBK 编码」的时候,替换成「GBK 字符集」基本上不影响表意。

 

那么 unicode 呢?unicode 也有编号。

UCS-2(定长,采用2字节表示)

是一种直接采用 unicode 编号的编码,但是它只有16位,所以只在编号范围 u0000 到 uFFFF 范围内的编码与 Unicode 的码位完全一致。

UTF-16与UCS-2的关系
UTF-16可看成是UCS-2的父集。在没有辅助平面字符(Surrogate Code Points)前,UTF-16与UCS-2所指的是同一的意思。但当引入辅助平面字符后,就称为UTF-16了。现在若有软件声称自己支持UCS-2编码,那其实是暗指它不能支持在UTF-16中超过2字节的字集。对于小于0x10000的UCS码,UTF-16编码就等于UCS码。

 

UTF-8(变长,采用1~3字节表示)

UCS-2 的问题:

  1. 由于用2个字节保存 ASCII (只需一个字节)太浪费了
  2. UCS-2 编码有大小端问题。

大小端序:

以汉字为例,Unicode 码是4E25,需要用两个字节存储,一个字节是4E,另一个字节是25。存储的时候,4E在前,25在后,这就是 Big endian 方式;25在前,4E在后,这是 Little endian 方式。

Unicode 编码中表示字节排列顺序的那个文件头,叫做BOM(byte-order mark),FFFE和FEFF就是不同的BOM。UTF-8文件的BOM是“EF BB BF”,但是UTF-8的字节顺序是不变的,因此这个文件头实际上不起作用。

 

UTF-8 编码规则:

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

UTF-8 编码是变长的。除了每个字符编码的「第一个字节」之外,其余所有字节,二进制表示都以 10 开始。这样,每个字符的第一个字节就变得特殊起来。

  • 一方面,首字节不以 10 开始,表达了「字符开始」这一信息;
  • 另一方面,除了 ASCII 范围内的单字节编码,其余多字节编码时,首字节的开始有多少位 1,就记录了这个字符占了多少个字节

因此:

① UTF-8 编码兼容ASCII 编码。

② UTF-8 的编码规则保证了字节顺序的确定性,因此没有大端序和小端序的差异,也就不需要 BOM。

 

 

参考文章


https://liam.page/2017/08/27/mojibake-in-Windows-Notepad-due-to-wrong-encoding-detect/

http://www.ruanyifeng.com/blog/2007/10/ascii_unicode_and_utf-8.html

 

posted on 2018-03-24 04:28  Lemo_wd  阅读(357)  评论(0编辑  收藏  举报

导航