家用电脑搭建网站,室内设计网站模板,免费网站空间注册,加强网站建设的原因最近在开发输入法程序时遇到一个小问题#xff0c;就是删除一个emoji时#xff0c;不能一次删干净#xff0c;需要执行两次操作才可以。Intuitively#xff0c;这肯定是java操作unicode字符的问题#xff0c;于是找了JAVA官方文档参考一下#xff0c;解决了这个问题… 最近在开发输入法程序时遇到一个小问题就是删除一个emoji时不能一次删干净需要执行两次操作才可以。Intuitively这肯定是java操作unicode字符的问题于是找了JAVA官方文档参考一下解决了这个问题这里做下简单总结。原文在这里有兴趣自己看。http://www.oracle.com/technetwork/articles/java/supplementary-142654.html注文章中提到的“JAVA字节”均指JAVA平台的16位字节请不要和C的8位字节搞混。首先需要知道标准Unicode字符是一个16位字符废话所以标准Unicode字符集包含65536个字符2的16次方嘛哥的数学很好的。但是仅仅65536个字符是远远不够用的尤其是为了包含我们伟大中华民族丰富多彩的文字反正我是不认识Unicode字符集进行了扩展扩展到了24位也就是最多可以包含1,112,064个字符。这里我们把标准Unicode字符集也就是前65536个字符叫做Basic Multilingual Plane (BMP)把超过16位以上的扩展字符集叫做supplementary characters。UTF-16是一种编码方式以16位无符号单元来编码Unicode字符如果对一个标准Unicode字符编码只需要占用一个UTF-16单元如果对扩展Unicode字符编码则需要占用两个UTF-16单元。我们都知道在C语言中一个primitive char占用一个字节也就是8位。但是在JAVA中一个primitive char占用16位与一个标准Unicode字符长度相等因为JAVA平台采用UTF-16进行编码。这样JAVA就很容易处理Unicode基本字符。但是对于Unicode的扩展字符在JAVA中就需要占用两个char也就是两个UTF-16单元。举个栗子大写字母A的Unicode值为U0041它属于Unicode的基本字符集所以它只占用一个UTF-16单元表示为[0041]。而字符的Unicode值为U10400它属于扩展Unicode字符集所以它占用两个UTF-16编码单元表示为[D801][DC00](一个中括号代表一个UTF-16单元中括号本身没意义。第一个单元叫做high-surrogates范围从 UD800 到 UDBFF第二个单元叫low-surrogates范围从 UDC00 到 UDFFF这个看起来很类似多字节编码。但是我说的是但是这里有一个非常重要的不同点从UD800 到 UDFFF 其实为UTF-16的保留值范围专门用作编码Unicode扩展字符集这个范围不被赋予任何实际的标准Unicode字符。也就是说在你的程序里只要判断一个字符是否属于这个范围内就可以知道这个字符是应该被当做一个独立的Unicode基本字符处理还是当做半个扩展Unicode字符。回到我一开始提到问题我在开发android输入法的时候当需要删除一个emoji时总是需要删除两次才能删干净。这是因为我用的emoji都是属于Unicode扩展字符集的在编辑框中占用了两个UTF-16单元而每执行一次删除操作只删除了一个UTF-16单元也就是一个JAVA字节而另一个单元没有被删除所以就会显示异常。这时候只要再删除掉另一个字节就算真正把这个emoji删除干净了。用户在实际的应用中肯定是把Unicode标准字符集和扩展字符集混合着使用也就是说有的字符占用1个java字节有的字符占用两个java字节。那么我在执行删除一个字符的操作时必须也要先去判断我是要一次性删除一个字节还是删除两个字节。这就很简单了按照我前面提到的规则先判断一下被操作的字符值是否处于[UD800,UDFFF](inclusive)之间如果是就说明被操作的字符不是一个有效的标准Unicode字符而是半个Unicode扩展字符那么只需要在程序中自动删除两个java字节就可以了。反之如果被处理的字符不属于[UD800,UDFFF]范围内那么这个字符就是一个标准的Unicode字符只需要按照一个java字节处理就可以了。理论清楚后我假设你清楚了其实也不难就是我表达的不清楚没办法工科人总是思维超越语言我再简单介绍一下java中相关的处理函数。Character.toChars(int codePoint)参数codePoint为Unicode值此函数将Unicode值转换为标准java字节数组。如果codePoint是Unicode标准字符则返回值只包含一个char如果codePoint是扩展Unicode字符则返回值包含2个char。例在程序中如果要输出一个Unicode扩展字符可以这样String.valueOf(Character.toChars(0x1F60E))Character.isLowSurrogate(char ch)判断一个字符是否是一个Unicode扩展字符的低16位编码。Character.isHighSurrogate(char ch)判断一个字符是否是一个Unicode扩展字符的高16位编码。 转载于:https://blog.51cto.com/yaorugang/1704142