字符串乱码的本质

·  阅读 11
字符串乱码的本质

字符串不论在c、go、java里面底层都是用字符数组去实现的,那字符如何在计算机当中存储的?

不论是字符还是数字,计算机只能用0和1来表示,字母a和b不外乎就是被存储在计算机中的时候被翻译成了0和1的组合,那按什么规则去进行翻译或映射的?所以有了unicode字符集的出现,unicode字符集是字符的映射表,它能够将字母a和字母b所表示的0和1这种组合表示出来。

0和1这种组合在unicode字符集中被称为一个码点,码点其实是一个数字,为什么是数字?因为0和1是二进制,二进制可以翻译成十进制数,所以当它翻译成十进制数之后,它就是一个数字。但是这里还有一个问题,就是unicode只是规定了这种映射关系,但却没有规定在计算机内的存储方式,比如字母a对应的码点规定为65,那65既可以用一个字节去表示,又可以用两个字节去表示,究竟是用一个字节还是两个字节呢?所以针对编码的实现方式会有多种,而utf-8就是其中一种,除此之外还有utf-16等,所以你可以把utf-8或gbk这种形式理解为是对unicode字符集的实现。

有了这个基础之后,来看下乱码到底是如何产生的?

乱码不外乎就是存储的时候是一种编码,拿出来的时候又是另外一种编码,两种编码格式对不上,在显示器上看到的就是乱码,

image.png

先来看下正常的一种流程,平时在编辑代码的时候在代码里面会输入一些关键字,像abc或中文之类的这种字符串,那这个字符串最终是要保存在磁盘上的,在磁盘上本质上也是用0和1这种格式去保存的,那要用什么格式把中文或字母翻译成0和1呢?这里软件a用的gbk编码格式保存的,那软件b同样在磁盘上面读取的时候用gbk编码翻译,如果按另外一种编码格式进行翻译就是我们看到的乱码,而显示器上面的乱码显示是通过软件往显示器上面输入的字节流,注意:只有当软件b用真正的gbk这种编码格式往显示器上面去输入字节流,显示器才能正常的显示我们的文本。

把软件a这一个字符串保存在磁盘上,软件b如果以gbk的方式解码那必然是正常的,那如果用utf-8,这里软件b就会告诉显示器这个字符串它是以utf-8的形式解码,所以显示器会对这个字符串按utf-8的形式进行解码展示,但是实际的字符串存储的格式却是以gbk这种编码格式保存的,所以必然会导致显示器上面看到的是乱码,这就是乱码产生的过程。

golang当中是怎么表示字符和字符串的?在golang里面其实是有一个类型叫做rune,rune其实就是unicode的一个码点,它本质上是一个int32类型来表示unicode的一个码点,

image.png

比如在golang当中表示一个汉字"五",如果这个五用单引号引起来,在golang里面会被编译器理解为一个char字符类型,字符在输出的时候,它输出的是一个数字,这个数字就是码点。

当十进制数被翻译成二进制数之后,就是这个字符在计算机当中真正存储的格式,可以在线的去看unicode输入字符"五"对应输出的码点是多少,

image.png

rune类型其实就是unicode的一个码点,所以在golang当中如果string字符串是以utf-8形式存储,那将这个字符串转换rune数组之后,每个rune代表的就是每一个字符,所以这也是为什么说go是原生支持unicode字符的原因,但前提是要保证你在编辑器编码的时候,字符指定的格式是utf-8格式。

开发当中遇到的一些编码问题

平时在用客户端发请求的时候会指定一个content type,比如application/x-www-form-urlencoded;charset=UTF-8,指定了utf-8,发网络请求的时候,内容其实是一个字节流,字节流以utf-8格式编码,客户端告诉服务器我的字节流是按什么格式编码的,服务器按照这种格式做相应的解码,服务器最后把解码之后的这些字节流按照某一个编码格式存储,服务端返回的content type,同样指定了charset,表示服务端返回给客户端的字节流是以什么格式编码的,客户端在接受到这种编码格式之后也会进行相应的解码操作。

在html网页,有一个meter标签。指定了网页是以什么格式编码保存的,比如在gbk的计算机上写了一个网页,把meter设置为gbk,因为往网页上面输入一个汉字,这个网页保存的时候是以输入之后的这部分字符串保存的编码,因为计算机默认是gbk的编码,所以保存的时候是以gbk格式保存的汉字,这个网页发到了网站上面,别人在看的时候比如用utf-8的机器看,其实是不会出现乱码的,因为浏览器会帮我们做这种转码的操作,浏览器会获取这个网页的meter,发现是gbk,浏览器装在utf-8的机器上面,它检测到了显示器是按utf-8进行显示,所以它会把我的网页上面的这些字节以utf-8形式进行一个转码,它会把gbk转成一个utf-8的形式 ,再把这部分字节流输出给显示器,显示器再进行展示,这样就不会乱码了,否则如果少了浏览器转码,用utf-8这种编码格式的计算机通过浏览器看gbk格式保存的网页就会出现乱码。

乱码的本质是由于显示器的解码方式是实际的字符编码方式不一样,所以要知道实际的字符编码方式并且要告诉显示器要按这种解码方式进行解码才行,如果是不同的解码方式,在告诉显示器之前,显示器或者软件得进行转码的操作,转码之后的那部分字节再输入给显示器,这样显示器就不会显示乱码了。

分类:
后端
标签:
收藏成功!
已添加到「」, 点击更改