Keywork: ANSI, GBK, UTF-8, Unicode, UTF-16, UTF-16LE, UTF-16BE, ASCII, ISO 8859-1, BOM, JAVA
一、ANSI码(American National Standards Institute),美国国家标准学会的标准码。
http://baike.baidu.com/view/1273097.htm
在简体中文系统下,ANSI 编码代表 GB2312 编码,在日文操作系统下,ANSI 编码代表 JIS 编码。
0x80~0xFF 范围的 2 个字节来表示 1 个字符(一般的中文汉字<简体中文系统中>)。
0x00~0x7F 之间的字符,依旧是1个字节代表1个字符(ASCII)。这一点是ANSI编码与Unicode(UTF-16)编码之间最大也最明显的区别。
如ANSI下“1”编码占用一个字节,用十六进制表示为:0x31;
UTF-16下“1”编码占用两个字节,用十六进制表示为:0x0031。
ANSI编码的BUG:
(Windows记事本)当新建文本文档只输入“联通”2字保存再打开时将是乱码。
其ANSI编码为:
(联)0xC1AA<二进制:11000001 10101010>
(通)0xCDA8<二进制:11001101 10101000>,
他们的二进制编码都恰好符合UTF-8标准(无BOM<byte oder mark>),所以再次打开时,就以UTF-8格式打开,于是就出现了乱码。
二、Unicode(统一码、万国码、单一码、标准万国码)是计算机科学领域里的一项业界标准,用以统一地体现和处理世界上大部分的文字系统,并为其编码。
http://zh.wikipedia.org/wiki/Unicode
Unicode是一张表,装有世界上大多数文字(英文字符,中文,法文……),它们都各自对应两个字节。
三、UTF-8(8-bit Unicode Transformation Format)是一种针对Unicode的可变长度字符编码(定长码),也是一种前缀码。
它可以用来表示Unicode标准中的任何字符,且其编码中的第一个字节仍与ASCII兼容,这使得原来处理ASCII字符的软件无须或只须做少部份修改,即可继续使用。因此,它逐渐成为电子邮件、网页及其他存储或传送文字的应用中,优先采用的编码。
UTF-8使用一至四个字节为每个字符编码。其中128个US-ASCII字符只需一个字节编码(Unicode范围由U+0000至U+007F),所以兼容ASCII(一个字节)
UTF-8是一种Unicode表标准的实现。
UTF-8的派生物:
1.Windows
虽然不是标准,但许多Windows程序(包括Windows记事本)在UTF-8编码的文件的开首加入一段字节串EF BB BF。这是字节顺序记号U+FEFF的UTF-8编码结果。对于没有预期要处理UTF-8的文本编辑器和浏览器会显示成ISO-8859-1字符
串""。
2.Java
在通常用法下,Java程序语言在通过InputStreamReader和OutputStreamWriter读取和写入串的时候支持标准UTF-8。但是,Java也支持一种非标准的变体UTF-8,供对象的系列化,Java本地界面和在class文件中的嵌入常数时使用的
modified UTF-8。
3.变种UTF-8
标准和变种的UTF-8有两个不同点。第一,空字符(null character,U+0000)使用双字节的0xc0 0x80,而不是单字节的0x00。这保证了在已编码字符串中没有嵌入空字节。因为C语言等语言程序中,单字节空字符是用来标志字符串结尾
的。当已编码字符串放到这样的语言中处理,一个嵌入的空字符将把字符串一刀两断。
第二个不同点是基本多文种平面之外字符的编码的方法。在标准UTF-8中,这些字符使用4字节形式编码,而在改正的UTF-8中,这些字符和UTF-16一样首先表示为代理对(surrogate pairs),然后再像CESU-8那样按照代理对分别编码。
这样改正的原因更是微妙。Java中的字符为16位长,因此一些Unicode字符需要两个Java字符来表示。语言的这个性质盖过了Unicode的增补平面的要求。尽管如此,为了要保持良好的向后兼容、要改变也不容易了。这个改正的编码系统
保证了一个已编码字符串可以一次编为一个UTF-16码,而不是一次一个Unicode码点。不幸的是,这也意味着UTF-8中需要4字节的字符在变种UTF-8中变成需要6字节。
因为变种UTF-8并 不是UTF-8,所以用户在交换信息和使用互联网的时候需要特别注意不要误把变种UTF-8当成UTF-8数据。
四、UTF-16是Unicode的其中一个使用方式。
UTF-16与UCS-2 (2-byte Universal Character Set)的关系:
UCS-2在Unicode2.0版本以后被取代;
produces exactly the same result as UTF-16 for 96.9% of all the code points in the range 0-0xFFFF
UCS-2编码规则与96.9%的Unicode的0-0xFFFF范围代码点相同。
UTF-16可看成是UCS-2的父集。在没有辅助平面字符Mapping of Unicode character planes(surrogate code points)前,UTF-16与UCS-2所指的是同一的意思。但当引入辅助平面字符后,就称为UTF-16了。现在若有软件声称自己支持
UCS-2编码,那其实是暗指它不能支持在UTF-16中超过2bytes的字集。对于小于0x10000的UCS码,UTF-16编码就等于UCS码。
五、ISO 8859-1,正式编号为ISOIEC 8859-1:1998,又称Latin-1;西欧语言;,是国际标准化组织内ISOIEC 8859的第一个8位字符集。
它以ASCII为基础,在空置的0xA0-0xFF的范围内,加入96个字母及符号.
与ASCII的区别,ASCII是7bit字符集,ISO 8859-1 为8bit字符集,那为什么UTF-8可以完全至此ASCII,却不是完全至此ISO 8859-1,因为在UTF-8标准中,一个Byte的字符需要是0xxxxxxx格式的(0x00 ~ 0x7F),但ISO-8859-1的部分字符
超过了这个范围。
"UTF-16", "UTF-16LE", "UTF-16BE"
当读取文件时("UTF-16"格式,且文件不为空),
其最最前端的两个字节就是(BOM)
其值为(0xFE 0xFF)表示Unicode big endian (BE)
其值为(0xFF 0xFE)表示Unicode little endian (LE)
"UTF-16", "UTF-16LE", "UTF-16BE"的区别在于:
测试如下(buffer,为从文件头部的读取的ByteBuffer),
//在字节数组的开头不带BOM
buffer.put("分散".getBytes("UTF-16LE"));
//"UTF-16BE"同上
输出……
//在字节数组的开头带BOM(似乎默认是BE)
buffer.put("分散".getBytes("Unicode"));
输出……
从文件中读取UTF-8,与通过字符串转化为UTF-8的区别:
String.getBytes("UTF-8")不带BOM(0xEF 0xBB 0xBF)
readUtf_8File(buffer);//带有BOM//直接从某一文件流中得到的最前端的buffer(ByteBuffer)