字符编码问题摘要

UCS只是规定如何编码,并没有规定如何传输、保存这个编码。
例如“汉”字的UCS编码是6C49,我可以用4个ASCII数字来传输、保存这个编码;也可以用UTF-8编码:3个连续的字节E6 B1 89来表示它。关键在于通信双方都要认可。
UTF-8、UTF-7、UTF-16都是被广泛接受的方案。UTF-8的一个特别的好处是它与ISO-8859-1完全兼容。
UTF是“UCS Transformation Format”的缩写。UCS可以看作是”Unicode Character Set”的缩写。
UTF-8就是以8位为单元对UCS进行编码。

—————
内码和”code page”
—————
目前Windows的内核已经支持Unicode字符集,这样在内核上可以支持全世界所有的语言文字。
但是由于现有的大量程序和文档都采用了某种特定语言的编码,例如GBK,Windows不可能不支持现有的编码,而全部改用Unicode。 Windows使用代码页(“code page”)来适应各个国家和地区。”code page”可以被理解为前面提到的内码。GBK对应的”code page”是CP936。
微软也为GB18030定义了”code page”:CP54936。但是由于GB18030有一部分4字节编码,而Windows的代码页只支持单字节和双字节编码,所以这个”code page”是无法真正使用的。

—————-
UTF的字节序和BOM
—————-
UTF-8以字节为编码单元,没有字节序的问题。
UTF-16以两个字节为编码单元,在解释一个UTF-16文本前,首先要弄清楚每个编码单元的字节序。例如“奎”的Unicode编码是594E,“乙”的Unicode编码是4E59。如果我们收到UTF-16字节流“594E”,那么这是“奎”还是“乙”?
Unicode 规范中推荐的标记字节顺序的方法是BOM。BOM不是“Bill Of Material”的BOM表,而是Byte order Mark。BOM是一个有点小聪明的想法:在UCS编码中有一个叫做”ZERO WIDTH NO-BREAK SPACE”的字符,它的编码是FEFF。而FFFE在UCS中是不存在的字符,所以不应该出现在实际传输中。UCS规范建议我们在传输字节流前,先传输 字符”ZERO WIDTH NO-BREAK SPACE”。这样如果接收者收到FEFF,就表明这个字节流是Big-Endian的;如果收到FFFE,就表明这个字节流是Little- Endian的。因此字符”ZERO WIDTH NO-BREAK SPACE”又被称作BOM。
UTF-8不需要BOM来表明字节顺序,但 可以用BOM来表明编码方式。字符”ZERO WIDTH NO-BREAK SPACE”的UTF-8编码是EF BB BF(读者可以用我们前面介绍的编码方法验证一下)。所以如果接收者收到以EF BB BF开头的字节流,就知道这是UTF-8编码了。Windows就是使用BOM来标记文本文件的编码方式的。