字符的编码方式(ASCII、ANSI、Unicode)

发布时间 2023-12-05 22:23:51作者: mjy66

本篇博客大致介绍了字符的三种编码格式:ASCII、ANSI、Unicode,并比较浅显的解释了其编码过程,在写这篇博客的时候,参考了以下链接:

【字符编码】彻底理解字符编码 - leesf - 博客园 (cnblogs.com)

一篇搞懂Unicode ANSI UTF8等字符编码 - 知乎 (zhihu.com)

UTF-8 到底是什么意思?unicode编码简介 - 知乎 (zhihu.com)

Unicode、UTF-8、UTF-16 终于懂了 - 知乎 (zhihu.com)

ANSI是什么编码? - malecrab - 博客园 (cnblogs.com)

​ 为什么要出现编码?都知道计算机中的所有信息都是用二进制字符串来表示的,对于计算机中的各种字符来说,必然要设计一种规则,将每个字符映射至唯一的二进制字符串。

1、ASCII

​ ASCII编码是最早出现的编码方式,因为计算机诞生在西方,他们的语言算上26个字母的大小写加标点符号也没超过128个,所以其使用一个字节来表示就可以了,一个字节8位,前7位刚好能表示128个,所以剩余的一位默认设置为0。

​ 字符和数值具体的对应关系可以参考:ascii码 | ascii码对照表

​ 然而计算机的发展迅速,越来越多的人使用,所以光是英文字符肯定是不够了,比如中文或者日文,肯定用ASCII码表示不了,所以就出现了ANSI。

2、ANSI

​ ANSI是ASCII的扩展,其向下包含ASCII,对于ASCII字符来说,其仍然是一个字节表示,但是对于非ASCII字符来说,其就使用两个字节。ANSI并不是某种语言特定的字符编码,其可以表示不同的编码,比如对于中国人来说,ANSI的编码就是GBK编码,对于英国人来说,还是ASCII编码,对于韩国人来说就是EUC-KR编码。比如数值"0xd0d6",对于GB2312编码来说,其就是“中”,但是对于BIG5(港澳台)编码来说,其就表示"笢"。你可以看成它的出现是为了微软公司为了将windows推广,让不同国家的人都能接受。

3、Unicode

​ 虽然ANSI对于不同地区都有不同的编码形式,但是在面临两个本地化编码表不同的系统的时候,就无法进行数据交互了,会出现乱码的情况。Unicode的出现解决了这个问题,其给所有的字符都分配了唯一的码值,这里并不是编码实现,而是分配码值,就是说每个中文或者英文都有对应的十六进制数来表示。

​ 编码实现又是什么呢?刚开始听上去会很奇怪,一个字不就是用数值来表示吗,比如“中”,Unicode给的码值是0x4e2d,那直接就用0x4e2d不就行了,但是要考虑一个问题,就是当一大堆码值放在一起的时候,该怎么去断句呢?比如说0x4e2d,在txt中它既可以看成是“中“,也可以看成是”-N“,就是既可以看成是一个整体,也可以22分,所以不同编码方式就可以简单看成是断句的方式或者断句的顺序。在Unicode中具体的编码方式有utf-8、utf-16等。

3.1 UTF-8

​ UTF-8是一种变长编码方式,使用1-4个字节进行编码。UTF-8完全兼容ASCII,对于ASCII中的字符,UTF-8采用的编码值跟ASCII完全一致。其编码的规则如下:

img

​ 上表表示如何从一个从Unicode 转化到UTF-8 , 对于前0x7F的字符,UTF-8编码和ASCII码是一一对应的。如果一个字符在000800-00FFFF 之间,那转化到UTF-8 需要用三字节模板,使用16个码位,每个x 就是一个码位。

​ 比如『汉』这个字的Unicode编码是0x6C49。0x6C49在0x0800-0xFFFF之间,使用3字节模板:1110xxxx 10xxxxxx 10xxxxxx。将0x6C49写成二进制是:0110 1100 0100 1001, 用这个比特流依次代替模板中的x,得到:11100110 10110001 10001001。

3.2 UTF-16

​ UTF-8是不定长的编码,使用1、2、3、4个字节编码,而UTF-16则只使用2或4个字节编码。UTF-16也是Unicode一种具体的编码实现。关于Unicode如何转化为UTf-16编码规则如下:

1、对于 Unicode 码小于 0x10000 的字符, 使用 2 个字节存储,并且是直接存储 Unicode 码,不用进行编码转换

2、对于 Unicode 码在 0x100000x10FFFF 之间的字符,使用 4 个字节存储,这 4 个字节分成前后两部分,每个部分各两个字节,其中,前面两个字节的前 6 位二进制固定为 110110,后面两个字节的前 6 位二进制固定为 110111, 前后部分各剩余 10 位二进制表示符号的 Unicode 码 减去 0x10000 的结果

3、大于 0x10FFFF 的 Unicode 码无法用 UTF-16 编码

​ UTF-16的编码形式又可以分为大字节序形式和小字节序形式,大字节序就是高位的字节数据存放在内存的低地址处,低位数据存放在内存高地址处,小字节序则反过来,在windows中有UTF-16 LEUTF-16 BE两种形式分别代表小字节序形式的UTF-16和大字节序形式的UTF-16。可以将一个只有一个”中“(0x4e2d)的txt保存为这两种格式,再在命令行中调用Format-Hex看看其背后的十六进制数是怎么样的:

​ 首先保存为小字节序的编码形式,FF FE表示这个txt文件的编码方式是UTF-16 LE,后面跟着的是2D 4E,就是将高位的数据保存在了内存的高位,低位的数据保存在了内存的低位。


​ 大字节序和小字节序是一个道理就不再解释了。