【什么是字符编码】
字符编码(英语:Character encoding)也称字集码
是把字符集中的字符,编码为指定集合中某一对象,以便文本在计算机中存储或通过网络进行传递。
说人话:计算机里只能存数字(2机制),所以如果文字字符想要进行存储的话,就需要把对应的文字字符转换为数字才能进行处理,而字符编码就是文字字符在计算机中和数值的对应关系,是人为定义的一种映射规则。比如:
ASCII码(一种字符编码规则)中 数值是65 用来映射 字符A
我们存储 A 这个字符,本质上存在内存中的是数值65对应的2进制是0100 0001
常见的一些字符编码规则有
每个国家针对自己国家语言制定的编码规则(因为语言文字的数量各不相同)
ASCII码(美国)、GB2312编码(中国)、Shift_JIS编码(日本)、Euc-kr(韩国)等等
世界通用的编码规则(把所有语言统一到一套编码里)
Unicode编码 以及 基于Unicode实现的编码规则
UTF-8、UTF-16、UTF-32
【为何会出现乱码】
我相信很多人在查看文本文件时,经常会看到如上图中的这种乱码。那么为什么会出现这样的乱码呢?
假设我们的一个文件是采用中国制定的GB2312编码进行编辑存储的,而此时我们并不使用GB2312这个编码规则去读取文件,而是采用其它的规则,比如日本制定的Shift_JIS编码读取该文件,那么由于编码格式的存读不统一就会造成乱码的出现。因为不同的编码规则,字符和数值的映射关系是不同的。
比如:130这个数值在法语编码中代表了é
,在希伯来语编码中却代表了字母Gimel
(ג
),在中文编码中又会代表另一个符号。
【ASCII码】
我们知道在计算机内部,所有的信息最终都是一个二进制值。
一个二进制数就是一位(bit),有0和1两种状态。一个字节(byte)是8个二进制数组成的,所以1 byte = 8 bit。
也就是说一个字节一共可以用来表示256种不同的状态,从00000000到11111111。如果每一个状态都代表一个符号的话,那么一个字节可以用来表示256个符号。
上个世界60年代,美国制定了一套算是最早的字符编码,制定了一套基于英文字符与二进制位之间的对应关系。这套标准被称为ASCII码,一直使用到今天。
ASCII码一共规定了128个字符的编码。比如:
字符 A = 65(十进制数)= 0100 0001(二进制数)
字符 1 = 49(十进制数)= 0011 0001(二进制数)等等
下图为ASCII码的对照表
这128个字符的编码规则,只占用了一个字节的后面7位,最前面的一位统一规定为0。 英文国家使用128个字符编码就足够了,但是如果用来表示其它国家的语言,128个符号是远远不够的,于是乎就出现了非ASCII码们。
【非ASCII码】
非ASCII码基本都是基于ASCII码进行的扩充,他们都保留了ASCII码0~127这段编码的规范。也就是说非ASCII码的前面部分往往是和ASCII码的规则是相同的。
对于一些欧洲国家,他们使用一个字节便可以表示完自己所有的文字,他们利用了字节中闲置的最高位编入新的符号,因为我们知道ASCII码的编码规则是:一个字节中的8位,只占用了一个字节的后面7位,最前面的一位统一规定为0。所以这些语言系统中文字较少的国家让最前面的一位可以为1,他们就可以为自己的文字在128~255这一段加入新的对应规则。
比如:130这个数值在法语编码中代表了é
,在希伯来语编码中却代表了字母Gimel
(ג
)
这种一个字节就把字符表示完的做法只适用于语言系统中文字较少的国家,因为他们的语言的字母是有限的。
对于使用象形文字的国家来说,一个字节完全不够用!比如中国,我们的汉字多达10万左右,一个字节最多也只能表示256种符号,是远远不够的。所以必须使用多个字节来表示一个符号。比如我们前面提到的中国的简体中文GB2312编码,是使用两个字节表示一个汉字,所以理论上来说可以表示256x256=65536个符号。
所以所谓的非ASCII码,就是指的除了ASCII码以外的编码格式,每个国家都至少有1种针对自己语言文字的编码格式,每一个编码格式中 数值和字符的对应关系都可能不相同。这也就造成了前面说到的乱码问题。在全世界范围内进行网络通信时,如果每个国家都使用不统一的编码格式,那么出现乱码的情况将随处可见。
因此随着互联网的发展,人们决定要制定一套全世界统一的的编码规则,将世界上所有的符号都纳入其中,为每一个符号赋予独一无二的编码(二进制数值)。那么这样就不会出现乱码问题,影响信息的传递了。
【Unicode】
Unicode可以理解为是 Unique Code 的简写,翻译过来是“唯一的编码”。
它出现的主要原因就是用来解决乱码问题的,它将世界上所有的符号都纳入其中,每一个符号都为其分配一个独一无二的二进制数表示它,那么乱码问题就会消失。
Unicode是一个很大的集合,现在的规模可以容纳100多万个符号,每个符号对应的二进制数都不一样。这样就确保了不同语言的字符不会再有冲突。
那么这样可能就存在一个问题了,就是有的符号用1个字节8位就可以表示了,有的符号可能需要使用2个字节16位甚至3个字节24位才能表示。就比如说ASCII码,它的存储规则就是一个字节存储一个字符,那么当我们使用Unicode编码时,到底用几个字节来存储字符呢?
因此我们需要注意:Unicode编码只是一个符号集,它只规定符号和二进制的对应关系,并没有规定这个二进制数值应该如何存储。
而UTF-8、UTF-16、UTF-32三种编码格式才是基于Unicode实现的具体编码方案
UTF-8编码:可变字节编码方案,可以根据实际情况使用1个、2个、3个、4个字节来存储字符
UTF-16编码:可变字节编码方案,可以根据实际情况使用2个、4个字节来存储字符
UTF-32编码:固定字节编码方案,用4个字节来存储字符
我们在这里主要讲解目前互联网中使用最广泛、最普及的UTF-8编码格式
【UTF-8】
UTF-8是Unicode的实现方式之一,它的最大特点是:它是一种变长的编码方式,可以使用1~4个字节表示一个字符,根据不同的符号而变化字节的长度。
它的编码规则主要有以下两点:
我们需要明确UTF-8和Unicode之间的关系:
Unicode是世界上所有符号对应二进制数据的关系集合
UTF-8是Unicode的实现方式之一:UTF-8 = Unicode符号集 + 变长的编码规则
【总结】
我们在进行网络游戏开发时,只要保证前后端的字符编码格式统一就可以避免乱码的出现,比如如果只有英文字符的情况下,我们可以统一使用ASCII码进行字符的2进制转换,如果有中文字符的情况下,可以选择使用GB2313编码格式进行转换。
但是,我建议大家,在进行文件存储、网络传输时,都采用UTF-8的编码格式,它相对其它格式来说在互联网通信中应用更广泛,更普遍,它包含各种语言符号。
关注唐老狮获取更多干货内容