JAVA中的UTF-16编码

一、UTF-16编码方法

目前,UNICODE字符值的范围从U+000000到U+10FFFF(20bit),UTF-16以两个字节为单位对其进行编码。

1字符值在U+0000到U+FFFF(注意U+D800到U+DBFF无定义)之间的字符(也叫做BMP,BasicMultilingualPlane),直接用两个字节表示。

2字符值在U+10000到U+10FFFF(共有0xFFFFF个字符)之间的字符(也叫做增补字符集,supplementarycharacters),需要用四个字节表示。

前两个字节的范围是U+D800到U+DBFF(也叫高代理项,high-surrogatesrange),

后两个字节的范围是U+DC00到U+DFFF(也叫低代理项,low-surrogatesrange)。

转换方式如下:

1.1将字符值减去0x10000,结果范围0x0000到0xFFFFF。

1.2将结果的高10bit与0xD800做逻辑或运算,低10bit与0xDC00做逻辑或运算,

1.3将两部分组合起来就是该字符值的UTF-16编码。

3根据存储顺序的不同,UTF-16分为UTF-16LE和UTF-16BE,Windows和Linux一般使用UTF-16LE,而苹果操作系统使用UTF-16BE。

二、JAVA中的UTF-16

0在JDK1.5之后JAVA才开始支持增补字符集,由JSR204(UnicodeSupplementaryCharacterSupport)实现。

1JAVA中使用char(两个字节)作为表示字符的单位。因此,JAVA中单个char是无法表示增补字符的,而且位于U+D800到U+DBFF和U+DC00到U+DFFF的char被视为无定义字符。

2在JAVA平台中,char[]、String、StringBuilder和StringBuffer类中采用了UTF-16编码,BMP字符用一个char表示,增补字符使用一对char表示。

3JAVA使用代码点(Unicodecodepointer)这个概念来表示范围在U+0000与U+10FFFF之间的字符值,代码单元(Unicodecodeunit)表示用于作为UTF-16编码的代码单元的16位char值。因此,在Character类的API中,可以看到很多包含codePoint的方法。

4String类中有关方法的分析

4.1在String中,索引值指的是代码单元,所以增补字符在String中占两个位置。

4.2intlength()方法返回的是代码单元的数量,如果字符串中含有增补字符,该方法返回的值并非实际的字符数。

4.3charcharAt(intindex)方法直接返回索引出的char值,不管该char是否为增补字符代理项。

4.4intcodePointAt(intindex)方法,这个方法实际上是调用Character.codePointAtImpl()方法实现,源码如下

staticintcodePointAtImpl(char[]a,intindex,intlimit){charc1=a[index++];if(isHighSurrogate(c1)){if(index<limit){charc2=a[index];if(isLowSurrogate(c2)){returntoCodePoint(c1,c2);}}}returnc1;}  所以,当index和index+1均小于length(),且index的char在高代理范围内,就返回增补字符的代码点,否则返回index的char值。

4.5intcodePointBefore(intindex),实际上调用Character.codePointBeforeImpl()方法。

staticintcodePointBeforeImpl(char[]a,intindex,intstart){charc2=a[--index];if(isLowSurrogate(c2)){if(index>start){charc1=a[--index];if(isHighSurrogate(c1)){returntoCodePoint(c1,c2);}}}returnc2;}  所以,当index-1和index-2均非负,且index-2的char在高代理范围内,index-1的char在低代理范围内,则返回增补字符的代码点,否则返回index-1的char值。

4.6intcodePointCount(intbeginIndex,intendIndex),调用Character.codePointCountImpl()

staticintcodePointCountImpl(char[]a,intoffset,intcount){intendIndex=offset+count;intn=0;for(inti=offset;i<endIndex;){n++;if(isHighSurrogate(a[i++])){if(i<endIndex&&isLowSurrogate(a[i])){i++;}}}returnn;}  所以,该方法可以真正计算出字符串中的字符数量。

4.7offsetByCodePoints(intindex,intcodePointOffset)这个方法主要是计算从index开始,接下来第codePointOffset个代码点的下标。

4.8intindexOf(intch),其他相关方法,如lastIndexOf()等,原理类似。

如果ch的大小在0x0000到0xFFFF之间时,返回值是第一次满足charAt(k)==ch时的k值

如果ch的大小超过0xFFFF,返回值是第一次满足codePointAt(k)==ch的k值

如果都不满足,返回-1

关于以上这些函数的用法,developWorks上有篇文章有详细的解释:http://www.ibm.com/developerworks/cn/java/j-unicode/

相关资料:

维基百科UTF-16词条http://zh.wikipedia.org/wiki/UTF-16

相关推荐