龙空技术网

【字符集一】字符集vs字符编码

长安君an 189

前言:

如今小伙伴们对“netgbk单字节”大约比较着重,朋友们都想要分析一些“netgbk单字节”的相关资讯。那么小编同时在网摘上网罗了一些有关“netgbk单字节””的相关文章,希望你们能喜欢,小伙伴们快快来学习一下吧!

一、字符集vs字符编码

「字符集」和「编码」等几个层次的概念被彻底分离且模块化的这样一个模型,其实是 Unicode 时代才得到广泛认同的。而对于 ASCII、GB2312、Big5 之类的遗留(legacy)方案,其字符集及其编码的关系基本是锁定的,所以常常用「字符编码」(character encoding)、「代码页」(code page)等概念来统称它们那样从字符到编码字节流的整体方案。比如 ASCII 本身就既是字符集又是编码方案。 1、字符集

字符集:字符集(character set)定义了字符和二进制的对应关系,为每个字符分配了唯一的编号。

可以将字符集理解成一个很大的表格,它列出了所有字符和二进制的对应关系,计算机显示文字或者存储文字,就是一个查表的过程。

2、字符编码

字符编码:而字符编码(character encoding)规定了如何将字符的编号存储到计算机中。为了区分一个字符到底使用了几个字节,就不能将字符的编号直接存储到计算机中,字符编号在存储之前必须要经过转换,在读取时还要再逆向转换一次,这套转换方案就叫做字符编码。

3、字符集vs字符编码

4、常见字符集

字符编码

说明

ASCII

这套编码是美国人给自己设计的,迄今为止共收录了 128 个字符

ISO/

IEC 8859

欧洲字符集,支持丹麦语、荷兰语、德语、意大利语、拉丁语、挪威语、葡萄牙语、西班牙语,瑞典语等,1987 年首次发布。ASCII 编码只包含了基本的拉丁字母,没有包含欧洲很多国家所用到的一些扩展的拉丁字母,比如一些重音字母,带音标的字母等,ISO/IEC 8859 主要是在 ASCII 的基础上增加了这些衍生的拉丁字母。

Shift_Jis

日语字符集,包含了全角及半角拉丁字母、平假名、片假名、符号及日语汉字,1978 年首次发布。

Big5

繁体中文字符集,1984 年发布,通行于台湾、香港等地区,收录了 13053 个中文字、408 个普通字符以及 33 个控制字符。

GB2312

简体中文字符集,1980 年发布,共收录了 6763 个汉字,其中一级汉字 3755 个,二级汉字3008 个;同时收录了包括拉丁字母、希腊字母、日文平假名及片假名字母、俄语西里尔字母在内的 682 个字符。

GBK

中文字符集,是在 GB2312 的基础上进行的扩展,1995 年发布。GBK 共收录了 21886 个汉字和图形符号,包括 GB2312 中的全部汉字、非汉字符号,以及BIG5 中的全部繁体字,还有一些生僻字。

GB18030

中文字符集,是对 GBK 和 GB2312 的又一次扩展,2000 年发布。GB18030 共收录 70244 个汉字,支持中国国内少数民族的文字,以及日语韩语中的汉字。

二、ASCII字符集

ASCII (American Standard Code for Information Interchange):美国信息交换标准代码。

看这个名字就知道,这套编码是美国人给自己设计的,他们并没有考虑欧洲那些扩展的拉丁字母,也没有考虑韩语和日语,我大中华几万个汉字更是不可能被重视。

ASCII 的标准版本于 1967 年第一次发布,最后一次更新则是在 1986 年,**迄今为止共收录了 128 个字符**,包含了基本的拉丁字母(英文字母)、阿拉伯数字(也就是 1234567890)、标点符号(,.!等)、特殊符号(@#$%^&等)以及一些具有控制功能的字符(往往不会显示出来)。

在 ASCII 编码中,大写字母、小写字母和阿拉伯数字都是**连续分布的**(见下表),这给程序设计带来了很大的方便。例如要判断一个字符是否是大写字母,就可以判断该字符的 ASCII 编码值是否在 65~90 的范围内。

ASCII 编码

标准 ASCII 编码共收录了 128 个字符,其中包含了 33 个控制字符(具有某些特殊功能但是无法显示的字符)和95 个可显示字符。

(完整的可以去我的博客看)

三、GBK字符集

GB2312 --> GBK --> GB18030 是中文编码的三套方案,出现的时间从早到晚,收录的字符数目依次增加,并且向下兼容。

GB2312 和 GBK 收录的字符数目较少,用 1~2 个字节存储;

GB18030 收录的字符最多,用 1、 2、4 个字节存储。

1、GB2312 和 GBK字符集

从整体上讲,GB2312 和 GBK 的编码方式一致,具体为:

1.1、对于 ASCII 字符,使用一个字节存储,并且该字节的最高位是 0,这和 ASCII 编码是一致的,所以说 GB2312 完全兼容 ASCII。

1.2、对于中国的字符,使用两个字节存储,并且规定每个字节的最高位都是 1

例如对于字母 A,它在内存中存储为 01000001;对于汉字中,它在内存中存储为 11010110 11010000。由于单字节和双字节的最高位不一样,所以字符处理软件很容易区分一个字符到底用了几个字节。

2、GB18030 字符集

GB18030 为了容纳更多的字符,并且要区分两个字节和四个字节,所以修改了编码方案,具体为:

1、对于 ASCII 字符,使用一个字节存储,并且该字节的最高位是 0,这和 ASCII、GB2312,GBK 编码是一致的。

2、对于常用的中文字符,使用两个字节存储,并且规定第一个字节的最高位是 1,第二个字节的高位最多只能有一个连续的 0(第二个字节的最高位可以是 1 也可以是 0,但是当它是 0 时,次高位就不能是 0 了)。注意对比 GB2312 和 GBK,它们要求两个字节的最高位为都必须为 1。

3、对于罕见的字符,使用四个字节存储,并且规定第一个和第三个字节的最高位是 1,第二个和第四个字节的高位必须有两个连续的 0

字符处理软件在处理文本时,从左往右依次扫描每个字节:

1,如果遇到的字节的最高位是 0,那么就会断定该字符只占用了一个字节;

2,如果遇到的字节的最高位是 1,那么该字符可能占用了两个字节,也可能占用了四个字节,不能妄下断论,所以还要继续往后扫描:

3,如果第二个字节的高位有两个连续的 0,那么就会断定该字符占用了四个字节;

4,如果第二个字节的高位没有连续的 0,那么就会断定该字符占用了两个字节。

先写这么多吧,后面博客会再进一步的说下数据在里面的存储分区。

四、Unicode 字符集

1、Unicode 字符集

ASCII、GB2312、GBK、Shift_Jis、ISO/IEC 8859 等地区编码都是各个国家为了自己的语言文化开发的,不具有通用性,在一种编码下开发的软件或者编写的文档,拿到另一种编码下就会失效,必须提前使用程序转码,非常麻烦。

人们迫切希望有一种编码能够统一世界各地的字符,计算机只要安装了这一种字编码,就能支持使用世界上所有的文字,再也不会出现乱码,再也不需要转码了,这对计算机的数据传递来说是多么的方便呀!

就在这种呼吁下,Unicode 诞生了。Unicode 也称为统一码、万国码;看名字就知道,Unicode 希望统一所有国家的字符编码。

Unicode 于 1994 年正式公布第一个版本,现在的规模可以容纳 100 多万个符号,是一个很大的集合。

有兴趣的读取可以转到 [

]() 查看 Unicode 包含的所有字符,以及各个国家的字符是如何分布的。

> Windows、Linux、Mac OS 等常见操作系统都已经从底层(内核层面)开始支持 Unicode,大部分的网页和软件也使用 Unicode,Unicode 是大势所趋。

>有的字符集在制定时就考虑到了编码的问题,是和编码结合在一起的,例如 ASCII、GB2312、GBK、BIG5 等,所以无论称作字符集还是字符编码都无所谓,也不好区分两者的概念。而有的字符集只管制定字符的编号,至于怎么存储,那是字符编码的事情,Unicode 就是一个典型的例子,它只是定义了全球文字的唯一编号,我们还需要 UTF-8、UTF-16、UTF-32 这几种编码方案将 Unicode 存储到计算机中

2、UTF

UTF 是 Unicode Transformation Format 的缩写,意思是“Unicode 转换格式”,后面的数字表明至少使用多少个比特位(Bit)来存储字符。

UTF-8:一种变长的编码方案,使用 1~6 个字节来存储;

UTF-32:一种固定长度的编码方案,不管字符编号大小,始终使用 4 个字节来存储;

UTF-16:介于 UTF-8 和 UTF-32 之间,使用 2 个或者 4 个字节来存储,长度既固定又可变。

2.1、UTF8

UTF-8 的编码规则很简单:

如果只有一个字节,那么最高的比特位为 0,这样可以兼容 ASCII;

如果有多个字节,那么第一个字节从最高位开始,连续有几个比特位的值为 1,就使用几个字节编码,剩下的字节均以 10 开头。

具体的表现形式为:

0xxxxxxx:单字节编码形式,这和 ASCII 编码完全一样,因此 UTF-8 是兼容 ASCII 的;

110xxxxx 10xxxxxx:双字节编码形式(第一个字节有两个连续的 1);

1110xxxx 10xxxxxx 10xxxxxx:三字节编码形式(第一个字节有三个连续的 1);

11110xxx 10xxxxxx 10xxxxxx 10xxxxxx:四字节编码形式(第一个字节有四个连续的 1)。

xxx 就用来存储 Unicode 中的字符编号。

下面是一些字符的 UTF-8 编码实例(绿色部分表示本来的 Unicode 编号):

2.2、UTF32

UTF-32 是固定长度的编码,始终占用 4 个字节,足以容纳所有的 Unicode 字符,所以直接存储 Unicode 编号即可,不需要任何编码转换。

2.3、UTF16

UFT-16 使用 2 个或者 4 个字节来存储。

对于 Unicode 编号范围在 0 ~ FFFF 之间的字符,UTF-16 使用两个字节存储,并且直接存储 Unicode 编号,不用进行编码转换,这跟 UTF-32 非常类似。

对于 Unicode 编号范围在 10000~10FFFF 之间的字符,UTF-16 使用四个字节存储,具体来说就是:将字符编号的所有比特位分成两部分,较高的一些比特位用一个值介于 D800~DBFF 之间的双字节存储,较低的一些比特位(剩下的比特位)用一个值介于 DC00~DFFF 之间的双字节存储。

3、对比以上三种编码方案

只有 UTF-8 兼容 ASCII,UTF-32 和 UTF-16 都不兼容 ASCII,因为它们没有单字节编码。

1、 UTF-8 使用尽量少的字节来存储一个字符,不但能够节省存储空间,而且在网络传输时也能节省流量,所以很多纯文本类型的文件(例如各种编程语言的源文件、各种日志文件和配置文件等)以及绝大多数的网页(例如百度、新浪、163 等)都采用 UTF-8 编码。

UTF-8 的缺点是效率低,不但在存储和读取时都要经过转换,而且在处理字符串时也非常麻烦。例如,要在一个 UTF-8 编码的字符串中找到第 10 个字符,就得从头开始一个一个地检索字符,这是一个很耗时的过程,因为 UTF-8 编码的字符串中每个字符占用的字节数不一样,如果不从头遍历每个字符,就不知道第 10 个字符位

于第几个字节处,就无法定位。

2、UTF-32 是“以空间换效率”,正好弥补了 UTF-8 的缺点,UTF-32 的优势就是效率高:UTF-32 在存储和读取字符时不需要任何转换,在处理字符串时也能最快速地定位字符。

例如,在一个 UTF-32 编码的字符串中查找第 10 个字符,很容易计算出它位于第 37 个字节处,直接获取就行,不用再逐个遍历字符了,没有比这更快的定位字符的方法了。

但是,UTF-32 的缺点也很明显,就是太占用存储空间了,在网络传输时也会消耗很多流量。所以UTF-32 在应用上不如 UTF-8 和 UTF-16 广泛。

3、UTF-16 可以看做是 UTF-8 和 UTF-32 的折中方案,它平衡了存储空间和处理效率的矛盾。对于常用的字符,40用两个字节存储足以,这个时候 UTF-16 是不需要转换的,直接存储字符的编码值即可。

>Windows 内核、.NET Framework、Cocoa、Java String 内部采用的都是 UTF-16 编码。UTF-16 是幕后的功臣,我们在编辑源代码和文档时都是站在前台,所以一般感受不到,其实很多文本在后台处理时都已经转换成了 UTF-16 编码。不过,UNIX 家族的操作系统(Linux、Mac OS、iOS 等)内核都采用 UTF-8 编码,

五、ANSI编码

在Windows系统中,ANSI编码代表本地编码的意思。换言之,在简体中文Windows操作系统中,ANSI 编码代表 GBK 编码;在日文Windows操作系统中,ANSI 编码代表 Shift_JIS 编码。

六、宽字符vs窄字符、源文件字符集vs运行字符集

参见我的另外一篇博客:[【字符集二】多字节字符vs宽字符])

标签: #netgbk单字节