字符编码详解(ASCII,Unicode,ANSI,UTF-16,UTF-8)

ASCII

ASCII(American Standard Code for Information Interchange)编码起源于电报码,1960年10月6日,美国标准协会(ANSI)的X3.2小组委员会举行第一次会议,开始了关于ASCII标准制定。第一版ASCII标准于1963年发布,在1967年经历了重大修改,在1986年期间经历了最近一次更新。ASCII开始基于英语字母表,将指定的128个字符编码成7位的二进制整数。其中95个编码字符是可以打印的,包括数字0-9,小写字母a-z,大写字母A-Z,还有一些标点符号。


Unicode

Unicode是一种计算机行业统一编码标准,其起源是为了解决各国编码之间的不兼容问题,创始人之一Joe Becker说为其取名'Unicode'是为了表明这是一种唯一的,统一的,通用的编码。Unicode最初使用16位二进制来表示所有语言中的字符,因为当时所有报纸和杂志的现代文字总和小于214 = 16,384。1991年3月,Unicode联盟在加利福尼亚成立,同年10月,第一版Unicode标准发布。1996年发布Unicode 2.0,加入了代理字符机制(Surrogate Characters Mechanism),将码域增加到了100多万。2000年以后,Unicode基本保持一年一更的节奏,截止到2017年最新发布的Unicode 10.0,已经拥有136,755个字符。


Unicode的代理字符机制是怎么实现的?

Unicode 2.0 将码域分为两部分,第一部分为“基础码域”,范围(U+0000 - U+FFFF)第二部分为“扩展码域”,范围(U+10000 - U+10FFFF)。由于Unicode依然保持基于16位二进制编码,为了实现“扩展码域”,采取的做法是从“基础码域”中预留两段代码域,如下面表格所示:

Code point area Name Total
U+D800 – U+DBFF High Surrogates 0x400
U+DC00 – U+DFFF Low Surrogates 0x400

一个高位代理码后面接一个低位代理码,就构成了一个扩展码点(supplementary code point)。煮个栗子:

U+D800 U+DC00 = U+10000

U+D801 U+DC00 = U+10001

......

U+DBFF U+DFFF = U+10FFFF

所以扩展码域总共能够编码0x100000=‭1048576‬个字符(0x400 * 0x400


Unicode码域总共分成了多少块?

17块,详情见下表:

字符编码详解(ASCII,Unicode,ANSI,UTF-16,UTF-8)_第1张图片


Unicode编码方法

Unicode定义了两种类型的编码方法:Unicode Transformation Format (UTF) 和 Universal Coded Character Set (UCS) 。UTF编码有UTF-8、UTF-16、UTF-32,UTF后面的数字代表每个代码值的位数。UCS编码有UCS-2,UCS-4,UCS后面的数字代码每个代码值字节数。UTF-8、UTF-16是最常用的两种编码,UCS-2是UTF-16的子集,已经被淘汰了,UCS-4和UTF-32在功能上等同。

UTF-8:可变长编码,兼容ASCII。

UTF-16:可变长编码。

UTF-32:定长编码。



UTF-16编码详解

历史:
UTF-16(16-bit Unicode Transformation Format),是一种可变长编码,用1或2个16位(2字节)代码单元进行编码。UTF-16是从早期的16位定长编码UCS-2发展而来,由于16位最多只能编码65,536个字符,随着需要使用的字符越来越多,这明显不够用。于是IEEE(Institute of Electrical and Electronics Engineers,电气与电子工程师协会)提出了UCS-4方案,用4字节编码一个字符。Unicode联盟觉得这个方案扯淡,因为这会浪费很多磁盘空间,而且很多厂商已经投入大量资源基于2字节进行技术开发。最终UTF-16作为一个折中方案在Unicode 2.0标准中发布。

编码方式:
U+0000-U+D7FF 和 U+E000-U+FFFF (BMP)
这段范围好说,一个16位代码单元(2字节)对应一个码点,总共编码妥妥的。

U+10000-U+10FFFF (SP)
0x10FFFF-0x10000,所以还剩下0xFFFFF个码点,转为二进制是11111111111111111111,不用数了,20位
高10位(能表示的数字范围:0x0000-0x03FF)加上0xD800作为第一个16位代码单元,范围是0xD800-0xDBFF
低10位(能表示的数字范围:0x0000-0x03FF)加上0xDC00作为第二个16位代码单元,范围是0xDC00-0xDFFF

上面的文字不好理解?看图表:

字符编码详解(ASCII,Unicode,ANSI,UTF-16,UTF-8)_第2张图片


举个栗子:

Unicode字符:U+10437(

先减去0x10000,结果为0x0437
高位:0x0437除以0x400等于0x0001,0x0001 + 0xD800 = 0xD801
低位:0x0437除以0x400后余0x0037,0x0037 + 0xDC00 = 0xDC37
所以UTF-16编码为:0xD801DC37
解码的话反过来就是了。


字节序方案:

UTF-16的一个代码单元是2字节,由于大多数通信协议和存储协议都是以字节单位,于是在存储UTF-16序列的时候就需要选择字节序。为了便于识别字节序,UTF-16引入了BOM(Byte Order Mark),插入在第一个实际代码值之前。U+FEFF(零宽度不间断空格,啥也不是)表示大端,U+FFFE(非字符)表示小端。UTF-16规定如果缺少BOM头,应假设字节序为大端,但事实上,因为windows默认使用小端,所以很多软件也默认使用小端,平台的力量还是大。

以上面的字符为例(U+10437,UTF-16:0xD801DC37):

小端:


大端:




UTF-8编码详解

UTF-8是一种可变长编码,使用1-4字节(8位)编码所有Unidoce字符。与ASCII兼容,Unicode前128个字符与ASCII是一一对应的,UTF-8使用一字节对其进行编码,并且在二进制值上与ASCII一样。UTF-8已经成为了万维网上的主导编码,截止到2018年5月,91.5%网页使用UTF-8编码。IMC推荐所有的e-mail程序使用UTF-8展示和创建邮件,W3C推荐将UTF-8作为XML和HTML的默认编码。


编码方式:

字符编码详解(ASCII,Unicode,ANSI,UTF-16,UTF-8)_第3张图片

举个栗子:
1.Unicode字符‘€’,U+20AC
2.根据上表可知所在区间为 U+0800-U+FFFF,所以需要3字节编码
3.0x02AC二进制为 0010 0000 1010 1100
4.对照上表,从右往左,用3中的二进制逐一替换表格的x
5.结果为1110 0010 1000 0010 1010 1100,十六进制:0xE282AC


字节序:

UTF-8编码的最小代码值单元是1字节,所以不存在字节序问题。但是很多Windows程序(Windows记事本)会在以UTF-8保持的文件最前加上 0xEF, 0xBB, 0xBF,这个通常称为BOM。


优势劣势:
优势:兼容ASCII;字符边界容易识别;小于U+0080的编码只需一个字节;每个编码单元以1字节为单位,不用考虑字节序问题。
劣势:编码U+0800-U+FFFF需要3字节


ANSI

ANSI编码没有明确定义,但是通常被用来指代Windows代码页(Windows code page),在英文系统上通常指Windows-1252代码页,在简体中文系统通常指Windows-936(在不同的windows系统上,可能指代不同的代码页)。事实上,“ANSI编码”这个名字是个错误用法,应为ANSI从来没有发表过这样的标准。


Windows-1252:
别名CP-1252,用一个字节,总共编码256个字符,在英文和一些西方的Windows系统上作为默认编码。

Windows-936:
别名CP-936,是Windows系统为简体中文设计的编码,最初只覆盖GB2312中的字符,但是随着Window95的发布,被扩展到覆盖大部分的GBK。

编码方案:
第一部分:使用1个字节编码,0x00-0x80和0xff。总共编码130个字符,前128个字符和ASCII兼容。

第二部分:使用2个字节编码,高字节加lead byte(首字节),低字节叫trail byte(尾字节),lead byte范围:0x81-0xfe(125),trail byte范围:0x40-0xfe(190),总共编码字符:23750


引用:
https://en.wikipedia.org/wiki/ASCII
https://en.wikipedia.org/wiki/Unicode
http://hauchee.blogspot.com/2015/05/surrogate-characters-mechanism.html
https://en.wikipedia.org/wiki/UTF-16
https://en.wikipedia.org/wiki/UTF-8
https://en.wikipedia.org/wiki/ANSI_(disambiguation)
https://en.wikipedia.org/wiki/Windows-1252
https://en.wikipedia.org/wiki/Code_page_936_(Microsoft_Windows)
https://unicode.org/Public/MAPPINGS/VENDORS/MICSFT/WindowsBestFit/

你可能感兴趣的:(字符编码,utf-8,ASCII,ANSI,Unicode)