写点什么

你真的懂 Unicode 编码吗?,理解 spring 原理哪本书好

用户头像
极客good
关注
发布于: 刚刚


Java 中的 UTF-8 其实和 mysql 的 uft8 都只能表示 3 个字节的字符,而 Java 中拥有和 utf8mb4 字符集一样表示范围的是 UTF-32 字符集。


于是我抱着尝试的心理,做了以下的 debug 调试:



UTF-32 和 UTF-8 不同,它是一个定长的字符集,什么叫定长呢?比如 UTF-8 字符集就比较鸡贼,如果是“1”这样的数字,他在 UTF-8 字符集中映射数字为 47,完全在 2 的 8 次方的表示范围内,也就说只要一字节就能满足了,这个时候 UTF-8 就把它转化成一字节的 byte[],而对于映射成几千几万的汉字来说,UTF-8 就会用长度为 2 或 3 的 byte[]来表示。而 UTF-32 就很“老实”了,无论你映射成的数字是 47,还是 47000,还是更大,他都用长度为 4 的 byte[]来表示(所以我们一般用 UTF-8,因为 UTF-32 会浪费很多内存空间)。


上图所示的,uft32BytesLength 的值为 28,可以反推出,UTF-32 判断的这个 mileage 字符串里面包含 7 个字符,也就是说,他把"??"准确地判断为是一个字,而不是两个普通字合在一起!


从源码中汲取营养




既然 JDK 能识别特殊字符,那我们学习源码怎么写的不就好了。


于是从 String#getBytes()方法一层层往下点,到最底一层,如下图:



JDK 就是通过这个方法来判断某个字符是普通字符还是属于特殊字符的一部分!


再点进去看这个方法:


![在这里插入图片描述](https://img-blog.csdnimg.cn/20201010141706176.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG


【一线大厂Java面试题解析+核心总结学习笔记+最新架构讲解视频+实战项目源码讲义】
浏览器打开:qq.cn.hn/FTf 免费领取
复制代码


9nLmNzZG4ubmV0L3dlaXhpbl80OTUyNzMzNA==,size_16,color_FFFFFF,t_70#pic_center)


这两段英文大致意思就是:


决定入参是否为 unicode 的代码单元,满足条件的字符并不是单独表示一个字,而是用来表示 UTF-16 的增补字符。



如上图所示,凡是落在’\uD800’到’\uDFFF’,也就是 55296 到 57343 之间的字符都是用来两两表示特殊字符的!


解决问题




代码如下:


public String filterUtf8mb4Character(String input) {


List<Character> list = Lists.newArrayList();


char[] charArray = input.toCharArray();


for (char c : charArray) {


if (!Character.isSurrogate(c)) {


list.add(c);


}


}


char[] outputArray = new char[list.size()];


for (int i = 0; i < list.size(); i++) {


outputArray[i] = list.get(i);


}


return new String(outputArray);


}


感想总结




任何小问题只要肯钻研都会有不一样的收获,这也是决定大神和普通程序员的一个标准。

用户头像

极客good

关注

还未添加个人签名 2021.03.18 加入

还未添加个人简介

评论

发布
暂无评论
你真的懂Unicode编码吗?,理解spring原理哪本书好