两个 "锟斤拷"="锟斤拷"?
关于作者:程序猿石头(ID: tangleithu),现任阿里巴巴技术专家,清华学渣,前大疆后端 Leader。欢迎关注,交流和指导!
本文首发于微信公众号,原文链接,转载请全文保留。
以一首七言绝句作为开篇:
手持两把锟斤拷
口中疾呼烫烫烫
脚踏千朵屯屯屯
笑看万物锘锘锘
� 为何物?
在上次石头哥发的这篇文章中 —— 你可能也会掉进这个简单的 String 的坑,讲述了因字符编码问题而连续踩坑的经历,文中有一个神奇的字符 “�”。
其实,这个 “�” 真是无处不在,比如大名鼎鼎的微信:
再比如,封面图中,单价22元的“锟斤拷锟斤拷”,再随便百度一把:
要弄清这个问题,还得先从编码谈起。
因为在计算机的眼里,都是二进制,具体用哪些二进制数字表示哪个符号,这就是编码。不要把编码想象得太复杂,其实就是一个很简单的 mapping。
比如大家所熟知的 ASCII 编码,规定了
二进制的0100 0001
,也就是十进制的65
,代表的含义就是大写字母 A
。
�
也是一种编码字符,就跟上面的 A
一样一样的,它是 UNICODE 编码方式中的一个特殊的字符,也就是 0xFFFD(65533),语义是一个占位符(REPLACEMENT CHARACTER),用来表达未知的,自己不认识的东西。
比如上篇文章中的实验截图的,红色部分圈出来的对应的字符,UTF-8 编码都不认识,所以按照 UNICODE 的定义,我就只好用统一的一个占位符 —— 0xFFFD(65533)
来表示。
为什么会出现“锟斤拷”?
我们接着上篇的例子来看, 如下图所示,仍然从 “程序猿石头” 对应二进制编码截取部分:
如上图所示,第 18 行的字节数组 new byte[] {-25, -119, -25, -116}
,UTF-8
恰好都不认识,因此只能用占位符替换。
这种情况,在编码转换过程中确实也比较常见,如果双方没沟通清楚,确实很容易出现互相不认识的情况。
在中文系统中,常见的字符编码是 GBK,这个时候,因为大家没提前商量清楚,我就默认按照 GBK 给你编码看看。
惊不惊喜意不意外……
其实是因为,�
用 UTF-8
编码后变成了 0xEFBFBD
(就是上面的字节数组 [-17, -65, -67]
),两个连起来就是 0xEFBFBDEFBFBD
,也就是上面的字节数组[-17, -65, -67, -17, -65, -67]
。
而 GBK 编码依然采用双字节编码方案,因此上面的 6 字节 0xEFBFBDEFBFBD
,就被拆成了 3 个 2 字节字符即 0xEFBF, 0xBDEF, 0xBFBD
对应 GBK 编码里面就是:锟(0xEFBF),斤(0xBDEF),拷(0xBFBD)
<,,
现在,你知道了吗?
留个作业题:开篇的七言绝句,你知道另外的梗是来自哪里吗?欢迎留言讨论。
最近看到一份来自阿里巴巴开源的学习资料,涵盖了大前端、客户端、服务端、算法等多个技术领域,全书内容⻚数1600+,现在分享给大家。点击原文获取。
上一篇: 将 MySQL 数据表字段从繁体中文转换为简体中文
下一篇: 锟斤拷?UTF-8与GBK互转乱码问题
推荐阅读
-
锟斤拷?UTF-8与GBK互转乱码问题
-
两个 "锟斤拷"="锟斤拷"?
-
经典乱码锟斤拷
-
一段 Java 代码将带您识别锟斤拷。
-
为什么UTF-8 和 GBK 会相互转换,为什么会一团糟?-锟斤拷 "是指在字节和字符的转换(编码和解码)过程中使用了不同的编码,找出编码和解码的编码,修改后使用同一种编码。 ===================== 补充 ========================== 在上面的文章中,其实一直回避了一个问题,那就是既然保存中的所有字符都需要转换成二进制,那么 java 是使用什么编码来保存字符的呢?这个问题我们其实可以不必深究,因为它对我们来说是透明的,我们只需假定 java 使用了某种可以表示所有字符的编码。由于这种透明性,我们可以假设 java 直接保存字符本身,就像上面所说的那样。 在 java 虚拟机中使用的是 unicode 字符集。
-
【锟斤拷�⊠是怎样炼成的】——两分钟帮你彻底弄懂计算机的编码原理
-
码农说码】手撕锟斤拷,彻底了解GB2312、GBK、Big5、ASCII、UTF-8、UTF-32的前世今生--⭐Unicode⭐。