Java – 字符编码详解

简介

本篇文章讲解计算机当中的字符编码原理,及乱码原因的讲解。

 

字符集

在计算机中,任意数据都是以二进制的形式来存储的,从计算机的容量讲起,计算机的容量计量单位有很多,ZB->PB->TB->GB->MB->KB->B->Bit

计算机中最小存储单元为字节(B),一字节由8个比特(Bit)组成,每个Bit都是0或1的二进制数表示。

 

ASCII字符集

为了计算机能表示字母,在美国,他们开明了一种编码,叫ASCII码表,ASCII码表由1个字节存储,规则是,第一个Bit位为0,后面的Bit位可以从0~1

00000000 ~ 01111111

因此,ASCII 码表一共可以表示 128 个字母,关于ASCII码表的内容,在这里不进行阐述。

 

GB2312字符集

对于中国来说,只有128个存储量的ASCII码表是远远不够的,所以中国在1980年,制定了属于中国使用的码表 GB2312 .

GB2312 包含了 6763 个简体汉字,和 7445 个图形字符,但是GB2312 只包含了简体汉子,对于台湾等繁体字,在GB2312中没有包含。

 

BIG5字符集

因为GB2312码表中,并不包含繁体字,对于台湾而言,他们急需要一个码表,来表示台湾的繁体字,所以台湾地区在1984年实施了BIG5字符集,其中共收录13053个中文字。

 

GBK字符集

为了解决简体和繁体字的码表统一,中国在2000年3月17日发布新的中文字符集,其中包含了 21003 个汉字,包含GB13000-1标准中的全部中日韩汉字,和BIG5编码中的所有汉字。

 

ANSI字符集

对于Windows操作系统而言,每个国家都有他们对应的语言,也有他们对应的字符集,因此微软为了解决多国字符集的问题,把字符集统称为ANSI字符集

 

Unicode字符集

因为全世界每个国家都给自己制定了属于自己的字符集,这样零散的字符集不利于软件信息的交流,于是在1990年美国成立统一码联盟(Unicode组织),置力于把所有国家的字符集都收集到一个字符集中,成为【万国码表】,于1994年发布1.0版本,目前还在更新字符集中。

 

字符存储规则

我们知道ASCII码,使用1字节进行存储字母,最多能表示128个字符,所以对于不同字符集而言,它们存储一个字符所需要的字节数是不一样的。

 

GB2312 和 GBK 编码规则

对于中国而言,字符数是非常多的,如果像ASCII码表一样,使用1字节来存储是远远不够

所以中国在研发字符集的时候,规定了,在GBK和GB2312字符集中,每一个字符使用 2 个字节进行存储表示,字节的第一个Bit必须为1,这与ASCII码中的第一个Bit必须为0作为区分,使计算机能识别出来,何时使用ASCII码来解码,何时使用GBK码来解码。

 

其存储的范围在

00000000 00000000 ~ 11111111 11111111

其中,GBK和GB2312兼容ASCII字符集,所以0开头的,就是字母,1开头就是中文。

 

Unicode编码规则

对于Unicode而言,Unicode也有需于它的编码规则,因为它包含了全世界所有国家的字符,因此,它需要更多字节来存储一个字符。Unicode 提出了三种编码规则

UTF-16

在开始时候,Unicode制定了UTF-16编码规则,UTF-16 使用 2~4 个字节进行存储,也就是说,它的存储范围在

00000000 00000000 ~ 11111111 11111111 11111111 11111111

这对于中文而言是非常好的,但是对于英文而言,每一个英文至少都要占用2个字节,这显然是非常浪费存储空间的。

 

UTF-32

UTF-32 是固定使用 32 位 4 个字节来存储字符的,其范围在

00000000 00000000 00000000 00000000 ~ 11111111 11111111 11111111 11111111

可想而知,UTF-32是非常浪费存储空间的,尤其是英文字母。

 

UTF-8

对于前两种编码方式而言,都太过浪费存储空间了,所以现在基本上不怎么使用,但是用的最多,就是 UTF-8.因为 UTF-8 所使用的是 1~4 个字节来保存,其范围在

00000000 ~ 11111111 11111111 11111111 11111111 

其中,为了让计算机区分什么时候读1个字节,什么时候4个字节,UTF-8做出以下规定

0xxxxxxxx                           表示一个字节表达一个字符
110xxxxx 10xxxxxx                    表示读两个字节表达一个字符
1110xxxx 10xxxxxx 10xxxxxx           表示读三个字节表达一个字符
11110xxxx 10xxxxxx 10xxxxxx 10xxxxxx  表示读四个字节表达一个字符

计算机通过识别前面的规则来判定需要读几个字节来表示一个字符。

其中,中文字使用3个字节表示,英文字母使用1个字节表示

 

乱码的产生

乱码的产生有两种可能,

一种是中文字需要2个或3个字节来存储,计算机在读取的时候,未完整读取所有字节。

另一种是字符编码有误。

 

读取未完整

举例子,一个中文字,在GBK(包括GB2312,下同)字符集中,是由2个字节进行存储的,如果计算机只读出1个字节,那么它所表示的字符,将不存在。

字母【a】
01100001

中文【汉】
10111010 10111010

当计算机取出字母 a 的字节时,转换二进制得出十进制 97,对比ASCII码表中的97,得出字母【a】.

当计算机以同样的方式读取中文字【汉】时,若计算机只读一个字节,那么转换二进制得出十进制为 -57 ,这在ASCII码中,并不能查到对应的字母,因而乱码,或不显示。

 

字符编码错误

这里使用GBK和UTF-8作举例

UTF-8中的【汉】
11100110 10110001 10001001

GBK中的【汉】
10111010 10111010

当计算机采用 GBK 字符集进行解码UTF-8中的【汉】时,会出取前两位字节,和最后一个字节作为分别计算,得出结果 59057 和 -119

通过在 GBK 码表中查找 59057 的字为【姹】,而-119 在GBK中不存在,因此最后得出的结果为【姹?】

 

这就是乱码的由来。

如果您喜欢本站,点击这儿不花一分钱捐赠本站

这些信息可能会帮助到你: 下载帮助 | 报毒说明 | 进站必看

修改版本安卓软件,加群提示为修改者自留,非本站信息,注意鉴别

THE END
分享
二维码
打赏
海报
Java – 字符编码详解
本篇文章讲解计算机当中的字符编码原理,及乱码原因的讲解。
<<上一篇
下一篇>>