Unicode 编码规则
ANSI,American National Standards Institute 美国国家标准学会,由这个标准学会制订的一种编码规则,也叫 MBCS(Muilti-Bytes Charecter Set,多字节字符集)。
在最初的时候,Internet 上只有一种字符集—— ANSI 的 ASCII 字符集,它使用 7 bits 来表示一个 字符,总共表示 128 个字符,其中包括了 英文字母、数字、标点符号等常用字符。 之后,又进行扩展,使用 8 bits 表示一个字符,可以表示 256 个字符,主要在原来的 7 bits 字符集的基础上加入了一些特殊符号。 后来,由于各国语言的加入,ASCII 已经不能满足信息交流的需要,为了能够表示其它国家的文字,各国在 ASCII 的基础上制定了自己的字符集,这些从 ANSI 标准派生的字符集被习惯的统称为 ANSI 字符集,它们正式的名称应该是 MBCS(Multi-Byte Chactacter System,即多字节字符系统)。 这些派生字符集的特点是以 ASCII 127 bits 为基础,兼容 ASCII 127,他们使用大于 128 的编码作为一个 Leading Byte,紧跟在 Leading Byte 后的第二(甚至第三)个字符与 Leading Byte 一起作为实际的编码。 这样的字符集有很多,我们常见的 GB-2312 就是其中之一。
不同 ANSI 编码之间互不兼容,当信息在国际间交流时,无法将属于两种语言的文字,存储在同一段 ANSI 编码的文本中。 一个很大的缺点是,同一个编码值,在不同的编码体系里代表着不同的字。这样就容易造成混乱,导致了 Unicode码 的诞生。 为了统一所有文字的编码,Unicode 应运而生。Unicode 把所有语言都统一到一套编码里,这样就不会再有乱码问题了。
Unicode 编码点分为 17 个平面(plane),每个平面包含 2^16(即65536)个码位(code point)。 17 个平面的码位可表示为从 U+xx0000 到 U+xxFFFF,其中 xx 表示十六进制值从 00 到 10 ,共计 17 个平面。
string hex = "6BD8ABDE"; byte[] hexByteArr = Enumerable.Range(0, hex.Length) .Where(x => x % 2 == 0) .Select(x => Convert.ToByte(hex.Substring(x, 2), 16)) .ToArray(); string word = UnicodeEncoding.Unicode.GetString(hexByteArr);
UTF-8 的编码规则:
(1) 对于ASCII码中的符号,使用单字节编码,其编码值与ASCII值相同。其中ASCII值的范围为0~0x7F,所有编码的二进制值中第一位为0(这个正好可以用来区分单字节编码和多字节编码)。
(2) 其它字符用多个字节来编码(假设用N个字节),多字节编码需满足:第一个字节的前N位都为1,第N+1位为0,后面N-1 个字节的前两位都为10,这N个字节中其余位全部用来存储Unicode中的码位值。
字节数 | Unicode | UTF-8编码 |
1 | 000000-00007F | 0xxxxxxx |
2 | 000080-0007FF | 110xxxxx 10xxxxxx |
3 | 000800-00FFFF | 1110xxxx 10xxxxxx 10xxxxxx |
4 | 010000-10FFFF | 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx |
对比 | UTF-8 | UTF-16 | UTF-32 | UCS-2 | UCS-4 |
编码空间 | 0-10FFFF | 0-10FFFF | 0-10FFFF | 0-FFFF | 0-7FFFFFFF |
最少编码字节数 | 1 | 2 | 4 | 2 | 4 |
最多编码字节数 | 4 | 4 | 4 | 2 | 4 |
是否依赖字节序 | 否 | 是 | 是 | 是 | 是 |
Unicode 误区
- Unicode 只不过是 16 比特编码。一些人误认为 Unicode 只不过是16比特编码,每个字符占用16比特,因此一共有65,536个可能的字符。实际上这是不正确的。这样是关于Unicode的最大误解,所以也难怪一些人会这么想。
- 任何未分配的代码点都可以用于内部用途?错。最终,那些未分配的地方都会被某个字符使用。你应该使用私有用途代码点,或非字符代码点。
- 每个Unicode代码点都表示一个字符?错。有许多非字符代码点(FFFE,FFFF,1FFFE,……)还有许多代理代码点、私有代码点和未分配的代码点,还有控制和格式“字符(RLM,ZWNJ,……)
-
字符映射是一对一的?错。映射关系也可能是:
- 一对多:(ß → SS )
- 上下文相关:(…Σ ↔ …ς 和 …ΣΤ… ↔ …στ… )
- 语言相关:( I ↔ ı 和 İ ↔ i )