面试百度被问:简单了解下为什么会乱码,怎么恢复?

计算机是如何存储字符的?

​ 大学都学过计算机相关的基础知识,计算机只能计算二进制数据,因为二进制表示起来最方便。计算机电子元器件表示两个状态很简单,比如高压和低压,对应的就是1和0。如果设计出10种状态,那么计算机的设计会相当复杂。

​ 计算机想存储我们现实世界的字符,也就是我们常用的汉子或者字母。最简单的方法就是把每个字符都对应一个数字,数字都能转为二进制,这样相当于计算机间接的存储了字符。实际上,计算机科学家们也的确是这么做的。由此,便诞生了各种字符集,各个国家的字符都有对应的数字。

都有哪些字符集

​ 计算机发明之初,没有考虑那么多。作为现代计算机的发源地,当时也只考虑了美国的需求。所以只需要128个字符,称之为ASCII编码或者ASCII字符集(叫法不同而已,但是我觉得叫字符集更准确)。128个字符,如果用数字一一对应,一共只需7位二进制数字。计算机存储的最小单位是byte,即8位。ASCII字符集把最高位设置为0,用剩下的7位来表示字符。下图便展示了ASCII中,数字与字符的对应关系。

​ 图中把ASCII字符集分为了两大部分,打印和非打印。打印部分好解释,就是会输出在显示设备上的,可以看看我们的键盘上,一般也都会有这些字符。非打印部分更多的是控制目的。比如NUL表示空字符,\n表示换行,\r表示回车等。

​ 对于美国来说,ASCII是够用了,但是其他很多国家显然就不够用了。下面简单说说一些常见的。ISO 8859-1和Windows-1252。这两个都加入了西欧字符,两者基本一样,ISO 8859-1号称是用于西欧国家的标准字符集,但是Windows-1252更常用些。

​ 中文的第一个标准字符集是GB2312,有大约7000个汉字和一些罕用词和繁体字。其使用两个字节表示汉字。GBK建立在GB2312的基础上,并向下兼容。共计包含了21000个汉字,其中包含了繁体字。GB18030进一步增强了GBK,同样可以向下兼容,共包含了76000个字符,其中有很多少数民族字符,以及中日韩统一字符。但是两个字节已经表示不了GB18030中的所有字符了,GB18030使用了长编码,有的字符是两个字节,有的是四个字节。两个字节的编码中,表示范围和GBK一样。除了以上表示中文的字符集外,还有个Big5,是针对繁体字的,广泛应用于湾湾省和香港那边。

​ 前面说了这么多,是不是觉得很麻烦。不同的国家地区,还得用不用的字符集。前面讲到的所有字符集统称为非Unicode字符集。为了解决每个国家不同字符集间的不兼容现状,便有了Unicode字符集。它做了一件事,就是给世界上所有字符都分配了一个唯一的数字编号,有110多万,但大部分都在0x0000~0xFFFF之间,即65536个。

​ **这些数字编号一般用16进制表示,但是要注意,只是分配了个数字编号,并不像上面的非Unicode字符集一样,这个数字也表示字符对应的二进制。**至于Unicode字符集中,每个字符对应的二进制是多少,有几种不同的方案,主要有UTF-8、UTF-16、UTF-32。

​ UTF-32最简单,也符合我们的正常逻辑。数字编号的二进制形式,就是这个字符对应的二进制。缺点就是,每个字符都用四个字节表示,显然对于常用字符这是非常浪费的。UTF-16和GB18030一样,有个用两个字节有的用四个字节。UTF-8使用最广,其使用的是变长字节,每个字符使用的字节个数与Unicode中的数字编号有关。编号小的用的字节就少,编号大的用的字节就多,字节个数从1~4不等。

乱码怎么恢复

​ 看到这里,为什么乱码相信你肯定知道了。无非就是使用了不同的字符集,导致解析错误。那么该怎么恢复乱码呢?如果你知道原编码方式最好,直接切换成对应的字符集即可。比如在一些可以切换编码方式的文本编辑器里、HTML的原信息设置、IDE的设置等。

​ 但是如果不知道的话,也没什么太好的方式,只能一个个尝试了。我们可以写个简单的小程序,通过遍历常见字符集,来试着解析出乱码的原有格式。以Java为例:String newStr = new String(str.getBytes(charsets[i]),charsets[j])。这句代码的意思就是:假设乱码str原来是charsets[j]编码的,被错误解析为charsets[i]编码的。在尝试前,切记要对原文件做备份,因为多次错误的解析和转换,可能很难再恢复成正常的字符了。

全部评论

相关推荐

04-08 23:14
已编辑
南阳理工学院 算法工程师
本人情况:26届双非本科,两段实习经历,目前拿到的都是实习的offer,一个校招的都没有,他们都说先实习,然后等拿到毕业证了直接转正,我又害怕干三个月给我叉出去面试题也发一下吧### 杭州问尔信息技术后端登录你是怎么做的?JWT令牌你了解过吗?他虽然是一段字符串,他表达了什么东西?怎么解析出来信息和过期时间?JWT令牌怎么续期?如果我拉黑一个账号,要怎么做?两种方案(有无redis)mongodb和mysql的区别?mongodb和mysql分别实用于什么项目?选型你会怎么选?数据库的事务,那些地方需要使用,那些地方不需要使用?他会影响什么性能?mysql和pgsql有什么差异你知道吗?消息队列 redis也有,为什么要用mq?前后端会部署吗?docker会用吗?内部通信前端 async和 await你知道吗?异步编程的原理是什么?vue3 为什么你改变一个字符串 前端会跟着改动AI工具会用什么?你会怎么用?### 仲财通常用的锁有哪些synchronize和ReentrantLock的区别分布式锁了解吗?分布式事务mysql表字段sql优化什么时候用索引索引什么时候会失效mysql事务ioc一些项目应用问题### 观妙科技项目问题...zset的架构是什么样子的线程池突然队列被打满了怎么办?如果上游和下游都无法控制,该怎么维护select * from user where age>20 order by update_time 索引设计检索过程是什么样的冒泡排序和快排,有什么区别怎么判断链表有没有环### 观妙科技-二面项目部分...线程池的核心参数有哪些你是怎么用线程池的JMMG1模型跳表介绍一下平衡二叉树TCP为什么要三次握手?说一下hashmap红黑树的特征你有什么学习的方法
牛马人的牛马人生:对学院本而言很强了
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务