当前位置:   article > 正文

byte数组转string乱码_彻底搞懂这烦人的编码与乱码!

byte转string乱码

我们平时在处理文本文件或者网络请求时,时不时会遇到乱码的情况,这篇文章就带你彻底搞懂编码和乱码

首先,我们要知道,在计算机中,一切都是用0和1来表示的。普通的txt文件、或者客户端发过来的数据等等,这些一切其实都是通过0和1转化而来的。「那它是怎样从0和1转化我们人能看懂的字母或汉字呢?」

ASCII

起初,计算机是由美国人发明的,而且那时候基本就在美国运行,因此,开始只考虑到了美国的需求,0和1只要能转化成英文字母和符号就行了,大概需要128个字符,所以就规定了0和1转化为这128个字符的规则,称作「ASCII编码」

计算机存储的最小单位是byte,而1byte有8个bit位,足够表示128个字符(「第一位用0表示,剩下7位从0-127分别表示128个字符」),因此ASCII编码就规定1byte对应一个英文字符,对应关系如下图:

f161debb890494ce61dc9c7146ff3cee.png
536d33bdb1e480af387a081939c5c858.png

虽然ASCII编码对于美国来说足够用了,但是其他国家显然是不够的,于是,各个国家就发明了自己的编码方式,比如我们「中国的GBK和GB2312等」。但是各个国家自己的编码也都会兼容ASCII编码(毕竟人家是鼻祖),前面说到ASCII编码的第一位为0,则其他国家自己的编码都会定义第一位为1,这样就能区分当前是ASCII编码还是自己国家的编码。

中国的编码

对于美国而言,一个字节就能表示所有的字符,但是在中国就不行了,光常见的汉字就有好几千个了,还不包括符号,因此,中国首先出现的编码形式是「GB2312」,它使用两个字节来表示,这种编码主要表示的是简体中文,不包括繁体字。

后来在GB2312的基础上,又发明了「GBK」编码(「GB2312表示的字符,用GBK显示完全一样」),增加了一万多个汉字,里面包括繁体字,这就是我们日常使用最常见的国内编码。此编码也是使用两个字节来表示。

在这里提一下,怎么看一个字符使用了几个字节,可以使用文本编辑器,我这里使用的是EmEditor,当然,其他的也行,如果是nodepad++则需要装一个插件查看二进制。

打开EmEditor,双击右下角的编码,选择GB2312

3bb15af37b6a9dca57d64b5fce73c409.png

接着输入一个字符,然后再双击右下角的编码,选择二进制(十六进制)视图。

c5217075a8736f5b20be83b91eafdbb2.png

可以看到,使用的是两个字节。这里再提一点,「为啥查看二进制,很多编辑器默认都是显示的是十六进制」?为啥不直接显示二进制,这是因为,一个字节有8个bit位,而一个十六进制数字能表示4个bit位,所以一个字节刚好可以使用两个十六进制来表示,就像上面显示的“B9 FA",两个表示一个字节,既简单又直观,如果直接使用二进制,要显示十六个0或1,眼都要看花掉。

因此,查看字符的二进制数据,最好是通过十六进制来查看。

世界统一编码

世界上有很多国家,每个国家都有自己特有的编码方式,这就导致了编码不统一,容易造成乱码的情况。那有什么方式可以让编码统一起来呢?可以通过「Unicode」

Unicode和其他编码方式不一样,它没有规定字符对应的二进制,也没有规定每个字符占多少个字节,「它只做了一件事,就是给世界上所有的字符分配了一个唯一的数字编号」,就像人的身份证一样,这是唯一的,它的范围从0x000000到0x10FFFF之间(十六进制以0x开头,二进制以0b开头,八进制以0开头),这个编号一般写成十六进制,前面再加上\u。例如”国“的Unicode就是”\u56fd“。

那这些编号怎么对应到二进制呢?可以采用UTF-8或者UTF-16和UTF-32等。我们平时使用的最多的就是「UTF-8」

UTF-8使用的字节跟Unicode编号的大小有关,编号越大,使用的字节越多,字节个数在1-4之间。对于大部分汉字而已,一个中文字符需要三个字节。而且UTF-8兼容ASCII。

乱码

我们平时出现乱码主要有三种情况。

「第一种」:用文本编辑器打开一个文本文件时,显示乱码。

这种情况是因为,我们平时有时候文本编辑器设置了固定UTF-8编码,但是突然打开一个GBK编码个文件,这时候就会出现乱码,里面只有汉字会乱码。

解决方法:只要将编辑器的编码方式设置成对应的即可。

「第二种」:在程序中读取文件,出现乱码。

这种情况是因为,在程序中读取文件一般都会设置编码,有时候省略编码就会读取系统的默认编码,如果设置的编码和文件的编码对应不上就会出现乱码。

解决方法:读取文件时设置的编码和文件编码保持一致。

「第三种」:接收请求数据出现乱码。

网络中传输的数据也都是二进制数据,所以在我们传输数据的时候,发送方指定一种编码将数据转成二进制通过网络传输到接收方,接收方再指定一种编码将二进制数据转成字符数据。如果发送方和接收方指定的编码不一致,则会出现乱码情况。

解决方法:发送方和接收方采用统一编码即可,一般都是采用UTF-8。

注意:不论是字符串转二进制,还是二进制转字符串都需要指定编码,例如Java中字符串的getBytes()方法将字符串转成字节数组,虽然方法可以不传编码格式,但内部会传入系统默认编码Charset.defaultCharset().name()。又比如String(byte bytes[], String charsetName)方法将字节数组转成字符串,也依然需要传入编码格式,如果不传就会采用系统默认编码。


扫一扫,关注我
499974ba1502f270455a2bc277139559.png

Java面试系列-线程相关(一)

2020-09-03

1655694dd7e0a2047a99947ccb047aaa.png

Java到底是引用传递还是值传递

2020-08-07

f3a3749911abb65f65e309ed8624265e.png

事务:不好意思,你被隔离了!

2020-07-23

e9839da34df2215607f27a2b757fe7b2.png

spring事务咋和新冠病毒一样,还会传染?

2020-07-05

1fe7ca1dc90c1ed80b3db205c6fa5a59.png

数据是怎么一步一步到服务器的

2020-06-18

16178125710844ee7218bdabe334a296.png
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/tf789/article/detail/61428
推荐阅读
相关标签
  

闽ICP备14008679号