java unicode补充字符带来的码点和代码单元问题

码点与代码单元

java string有两种判定字符的方式,一种是以码点,一种以代码单元,简单讲,码点就是真正的字符,代码单元是按大小即char型长度2个字节划分字符串。
所以length和charat方法都不能正确的表示我们所认为的字符数量个字符位置

关于 Character 摘自jdk文档

char数据类型(因此Character对象封装的值)基于原始Unicode规范,其将字符定义为固定宽度的16位实体。 Unicode标准已经被更改为允许其表示需要超过16位的字符。 法定代码点的范围现在是U + 0000到U + 10FFFF,称为Unicode标量值 。 (请参阅Unicode标准中U + n符号的 definition。 )

The set of characters from U+0000 to U+FFFF有时被称为基本多语言平面(BMP) 。 其代码点大于U + FFFF的Characters称为补充字符 s。 Java平台在char阵列和String和StringBuffer类中使用UTF-16表示形式。 在该表示中,补充字符表示为char值,第一个来自高替代范围( uD800-  uDBFF),第二个来自低代理范围( uDC00-  uDFFF)。

因此,值char表示基本多语言平面(BMP)代码点,包括代码代码点或UTF-16编码的代码单元。 一个int值代表所有Unicode代码点,包括补充代码点。 int的较低(最低有效)21位用于表示Unicode码点,而高(最高有效)11位必须为零。 除非另有说明,关于补充字符和char值的行为如下:

仅接受char值的方法不能支持补充字符。 他们将char值从代理范围视为未定义的字符。 例如, Character.isLetter('\uD840')返回false ,即使这个特定值如果后面是字符串中的任何低代理值都将代表一个字母。
接受int值的方法支持所有Unicode字符,包括补充字符。 例如, Character.isLetter(0x2F81A)返回true因为代码点值代表一个字母(CJK表意文字)。

关于unicode-16摘自百度

UTF-16编码以16位无符号整数为单位。我们把Unicode
unicode
unicode
编码记作U。编码规则如下:
如果U<0x10000,U的UTF-16编码就是U对应的16位无符号整数(为书写简便,下文将16位无符号整数记作WORD)。
如果U≥0x10000,我们先计算U'=U-0x10000,然后将U'写成二进制形式:yyyy yyyy yyxx xxxx xxxx,U的UTF-16编码(二进制)就是:110110yyyyyyyyyy 110111xxxxxxxxxx。
为什么U'可以被写成20个二进制位?Unicode的最大码位是0x10FFFF,减去0x10000后,U'的最大值是0xFFFFF,所以肯定可以用20个二进制位表示。例如:Unicode编码0x20C30,减去0x10000后,得到0x10C30,写成二进制是:0001 0000 1100 0011 0000。用前10位依次替代模板中的y,用后10位依次替代模板中的x,就得到:1101100001000011 1101110000110000,即0xD843 0xDC30。
按照上述规则,Unicode编码0x10000-0x10FFFF的UTF-16编码有两个WORD,第一个WORD的高6位是110110,第二个WORD的高6位是110111。可见,第一个WORD的取值范围(二进制)是11011000 00000000到11011011 11111111,即0xD800-0xDBFF。第二个WORD的取值范围(二进制)是11011100 00000000到11011111 11111111,即0xDC00-0xDFFF。
为了将一个WORD的UTF-16编码与两个WORD的UTF-16编码区分开来,Unicode编码的设计者将0xD800-0xDFFF保留下来,并称为代理区(Surrogate):
D800-DB7F
High Surrogates
高位替代
DB80-DBFF
High Private Use Surrogates
高位专用替代
DC00-DFFF
Low Surrogates
低位替代
高位替代就是指这个范围的码位是两个WORD的UTF-16编码的第一个WORD。低位替代就是指这个范围的码位是两个WORD的UTF-16编码的第二个WORD。那么,高位专用替代是什么意思?我们来解答这个问题,顺便看看怎么由UTF-16编码推导Unicode编码。
如果一个字符的UTF-16编码的第一个WORD在0xDB80到0xDBFF之间,那么它的Unicode编码在什么范围内?我们知道第二个WORD的取值范围是0xDC00-0xDFFF,所以这个字符的UTF-16编码范围应该是0xDB80 0xDC00到0xDBFF 0xDFFF。我们将这个范围写成二进制:
1101101110000000 11011100 00000000 - 1101101111111111 1101111111111111
按照编码的相反步骤,取出高低WORD的后10位,并拼在一起,得到
1110 0000 0000 0000 0000 - 1111 1111 1111 1111 1111
XML
XML
即0xe0000-0xfffff,按照编码的相反步骤再加上0x10000,得到0xf0000-0x10ffff。这就是UTF-16编码的第一个WORD在0xdb80到0xdbff之间的Unicode编码范围,即平面15和平面16。因为Unicode标准将平面15和平面16都作为专用区,所以0xDB80到0xDBFF之间的保留码位被称作高位专用替代[1] 。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值