在碰到这个问题之前,我对UTF-8的理解只停留在一种unicode编码的认识上。
在超出字符集编码区间的范围外的字符,转化成Utf-8编码时会在文件头中加上标识,以便解析器能够准确识别文件的编码,如果去掉以后将会导致编码异常。。
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"。
什么是UCS:
国际标准 ISO 10646 定义了通用字符集[1](Universal Character Set,UCS), UCS 是所有其他字符集标准的一个超集。它保证与其他字符集是双向兼容的,就是说,如果你将任何文本字符串翻译到 UCS格式,然后再翻译回原编码,你不会丢失任何信息。
SO 10646 定义了一个 31 位的字符集. 然而,在这巨大的编码空间中,迄今为止只分配了前 65534 个码位 (0x0000 到 0xFFFD)
这个 UCS 的 16位子集称为 基本多语言面 (Basic Multilingual Plane,BMP). 将被编码在 16 位 BMP 以外的字符都属于非常特殊的字符(比如象形文字),且只有专家在历史和科学领域里才会用到它们. 按当前的计划,将来也许再也不会有字符被分配到从 0x000000 到 0x10FFFF 这个覆盖了超过 100 万个潜在的未来字符的 21 位的编码空间以外去了. ISO 10646-1 标准第一次发表于 1993 年,定义了字符集与 BMP 中内容的架构. 定义 BMP 以外的字符编码的第二部分 ISO 10646-2 正在准备中,但也许要过好几年才能完成. 新的字符仍源源不断地加入到 BMP 中,但已经存在的字符是稳定的且不会再改变了.UCS 不仅给每个字符分配一个代码,而且赋予了一个正式的名字. 表示一个 UCS 或 Unicode 值的十六进制数,通常在前面加上 "U+",就象 U+0041 代表字符"拉丁大写字母A". UCS 字符 U+0000 到 U+007F 与 US-ASCⅡ(ISO 646) 是一致的,U+0000 到 U+00FF 与ISO 8859-1(Latin-1) 也是一致的. 从 U+E000 到 U+F8FF,已经 BMP 以外的大范围的编码是为私用保留的.UCS的实际表现形式为UTF-8/UTF-16/UTF-32编码
UTF-8不需要BOM来表明字节顺序,但可以用BOM来表明编码方式。字符"ZERO WIDTH NO-BREAK SPACE"的UTF-8编码是EF BB BF(读者可以用这个编码方式测试下:)。所以如果接收者收到以EF BB BF开头的字节流,就知道这是UTF-8编码了。
Windows就是使用BOM来标记文本文件的编码方式的。
原来BOM是在文件的开始加了几个字节作为标记。有了这个标记,一些协议和系统才能识别。好,看看怎么加上这写字节。