首页 > 编程知识 正文

16斤什么概念,utf-8编码是什么意思

时间:2023-05-04 20:05:31 阅读:22673 作者:1050

每个字符集都有唯一的编号,您可以从该编号中找到相应的字符。 在编程中我们经常使用文字,但使用文字的前提是把文字放在内存中。 毫无疑问,放入内存的只是字符的编号,不是真正的字符实体。

这就提出了问题。 怎样才能把字符号码放在内存里?

对于ASCII字符集,这很简单。 ASCII总共包含128个字符,正好可以以7位(Bit )存储,但考虑到计算机一般以字节(Byte )为基本单位,出于操作的考虑,以1字节(即8位)存储ASCII 这样就浪费了1比特,但读写效率提高了。

但是,对于Unicode,问题并不是那么简单。 Unicode目前包含数百万个字符。 高位字符可以存储1字节,低位字符可以存储3字节。 可以为所有字符分配3字节内存,也可以为较小的字符分配1字节或2字节内存,为较大的字符分配3字节内存。

这两个方案各有优缺点,请读者看一下分析。

字符集和字符编码不是概念。 字符集定义字符和二进制文件之间的对应关系,并为字符指定唯一的编号。 字符编码规定字符的编号存储在内存中的方法。 有些字符集是考虑到编码问题而创建的,并与编码结合在一起。 有些字符集只是决定字符的号码,如何编码是别人的事。 方案1 :为每个字符分配固定长度内存的一种方案是为每个字符分配固定长度内存,该内存必须足够大,可以容纳所有字符编号。 这种方法最简单,将字符编号直接放入内存即可,不需要转换,以后在字符串中放置字符和修改字符也非常简单。

字符串是一系列连续的字符,按顺序存储在内存中。 在c语言中,字符串用双引号“”括起来。 当前的Unicode包含数百万个字符,存储所有字符编号至少需要3个字节。 假设字符串' A3中'的unicode值(十六进制格式)分别为2A、31、DA49和BB672C,则存储在内存中的格式如下:

在大多数字符集中,常用字符的编号往往很小,而罕见字符的编号往往很大,包括Unicode。

a和3是ASCII编码中的字符,Unicode有意保留原ASCII中字符的编号,以便与ASCII兼容,因此英文和阿拉伯数字在Unicode中的编号非常小,一个字节就足够了。 里面是汉字,号码很大,一般能容纳两个字节。 可以看作是极其罕见的,或者只在极少数地区使用的文字。 这样的字符号比较大,有时需要3个字节。

是人民币符号,是汉字文化的一部分,和其他汉字一样,实际上是用两个字节保存的,这里说是为了演示故意犯错误需要三个字节。 上图中灰色背景的字节是未使用的字节,它们是被浪费的内存空间的一部分。 这就是用固定长度的内存存储字符号码的缺点。 因为常用的字符号码很小,所以这个方案浪费了很多内存空间。 在美国、加拿大、英国等以英语为中心的国家,内存使用率甚至还不到50%。

方案2 )为每个字符分配最小内存既然上述方案有缺点,就试着改进一下。 改善我的想法也是明确的。 压缩空闲内存,为每个字符分配尽可能少的字节。 例如,对于a和3,一个字节就足够了,其中两个字节就足够了,如下图所示。

这样就没有空闲字节了,不再浪费内存空间,但出现了新的问题。 如果我不告诉你,你知道为什么2A代表一个字,而2A31或2A31DA代表一个字吗? 后面的文字也有同样的问题。

在第一种情况下,每个字符占用的字节数是固定的,可以轻松区分每个字符。 在这种方式中,字符所占的字节数不同,字符之间也没有特别的标记,计算机无法确定字符。

这种方式需要改进,每个字符编码必须具有不同的特征,字符处理程序也需要调整,必须根据这些特征识别不同的字符。

要使每个字符编码具有不同的特征,可以从两个方面入手。

1 )一是从字符集本身入手,在设计字符集时,有意使不同的字符编号具有不同的特征。

例如,对于编号小的单字节字符,可以规定该字符编号的最高有效位(Bit )必须为0。 对于编号较大且以2字节存储的字符,字符编号的高位字节的最高位必须为1,低位字节的最高位必须为0。 对于编号较大且需要存储3字节的字符,此字符编号所有字节的最高有效位必须为1。

程序在查找字符时,从前面开始依次扫描,如果发现当前字节的最高有效位为0,则将该1字节作为字符编号。 如果发现当前字节的最高有效位为1,则继续向后扫描;如果后续字节的最高有效位为0,则将2个字节编号为1个字符;如果后续字节的最高有效位为1,则将相邻的3个字节编号为1个字符。

这种方式的缺点很明显,字符集不连续,中间留下大量空白区域,这些空白区域无法定义

任何字符。

 

2) 二是从字符编号下手,可以设计一种转换方案,字符编号在存储之前先转换为有特征的、容易定位的编号,读取时再按照相反的过程转换成字符本来的编号。

 

那么,转换后的编号要具备什么样的特征呢?其实也可以像上面一样,根据字节的最高位是 0 还是 1 来判断字符到底占用了几个字节。

 

相比第一种方案,这种方案有缺点也有优点:

 

缺点就是多了转换过程,字符在存储和读取时要经过转换,效率低;优点就是在制定字符集时不用考虑存储的问题,可以任意排布字符。

 

Unicode 到底使用哪种编码方案

Unicode 是一个独立的字符集,它并不是和编码绑定的,你可以采用第一种方案,为每个字符分配固定长度的内存,也可以采用第二种方案,为每个字符分配尽量少的内存。

 

需要注意的是,Unicode 只是一个字符集,在制定的时候并没有考虑编码的问题,所以采用第二种方案时,就不能从字符集本身下手了,只能从字符编号下手,这样在存储和读取时都要进行适当的转换。

 

Unicode 可以使用的编码有三种,分别是:

UFT-8:一种变长的编码方案,使用 1~6 个字节来存储;UFT-32:一种固定长度的编码方案,不管字符编号大小,始终使用 4 个字节来存储;UTF-16:介于 UTF-8 和 UTF-32 之间,使用 2 个或者 4 个字节来存储,长度既固定又可变。

 

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

1) UTF-8

UTF-8 的编码规则很简单:如果只有一个字节,那么最高的比特位为 0;如果有多个字节,那么第一个字节从最高位开始,连续有几个比特位的值为 1,就使用几个字节编码,剩下的字节均以 10 开头。

 

具体的表现形式为:

0xxxxxxx:单字节编码形式,这和 ASCII 编码完全一样,因此 UTF-8 是兼容 ASCII 的;110xxxxx 10xxxxxx:双字节编码形式;1110xxxx 10xxxxxx 10xxxxxx:三字节编码形式;11110xxx 10xxxxxx 10xxxxxx 10xxxxxx:四字节编码形式。

 

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

 

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

 

字符Næ⻬Unicode 编号(二进制)010011101110011000101110 11101100Unicode 编号(十六进制)4EE62E ECUTF-8 编码(二进制)0100111011000011 1010011011100010 10111011 10101100UTF-8 编码(十六进制)4EC3 A6E2 BB AC

对于常用的字符,它的 Unicode 编号范围是 0 ~ FFFF,用 1~3 个字节足以存储,只有及其罕见,或者只有少数地区使用的字符才需要 4~6个字节存储。

2) UTF-32

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

3) UTF-16

UFT-16 比较奇葩,它使用 2 个或者 4 个字节来存储。

 

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

 

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

 

如果你不理解什么意思,请看下面的表格:

 

Unicode 编号范围
(十六进制)具体的 Unicode 编号
(二进制)UTF-16 编码编码后的
字节数0000 0000 ~ 0000 FFFFxxxxxxxx xxxxxxxxxxxxxxxx xxxxxxxx20001 0000---0010 FFFFyyyy yyyy yyxx xxxx xxxx110110yy yyyyyyyy 110111xx xxxxxxxx4

 

位于 D800~0xDFFF 之间的 Unicode 编码是特别为四字节的 UTF-16 编码预留的,所以不应该在这个范围内指定任何字符。如果你真的去查看 Unicode 字符集,会发现这个区间内确实没有收录任何字符。

 

 

UTF-16 要求在制定 Unicode 字符集时必须考虑到编码问题,所以真正的 Unicode 字符集也不是随意编排字符的。

总结

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

 

如果你希望查看完整的 Unicode 字符集,以及各种编码方式,请猛击:https://unicode-table.com/cn/

虽然这个网站有时候无法访问,但它是最好的一个查看 Unicode 字符集的网站。 GB2312、Shift-JIS 等国家(地区)字符集怎么编码

GB2312、GBK、Shift-JIS 等特定国家的字符集都是在 ASCII 的基础上发展起来的,它们都兼容 ASCII,所以只能采用变长的编码方案:用一个字节存储 ASCII 字符,用多个字节存储本国字符。

 

以 GB2312 为例,该字符集收录的字符较少,所以使用 1~2 个字节编码。

对于 ASCII 字符,使用一个字节存储,并且该字节的最高位是 0;对于中国的字符,使用两个字节存储,并且规定每个字节的最高位都是 1。

 

 

由于单字节和双字节的最高位不一样,所以很容易区分一个字符到底用了几个字节。

宽字符和窄字符(多字节字符)

有的编码方式采用 1~n 个字节存储,是变长的,例如 UTF-8、GB2312、GBK 等;如果一个字符使用了这种编码方式,我们就将它称为多字节字符,或者窄字符。

 

有的编码方式是固定长度的,不管字符编号大小,始终采用 n 个字节存储,例如 UTF-32、UTF-16 等;如果一个字符使用了这种编码方式,我们就将它称为宽字符。

 

Unicode 字符集可以使用窄字符的方式存储,也可以使用宽字符的方式存储;GB2312、GBK、Shift-JIS 等国家编码一般都使用窄字符的方式存储;ASCII 只有一个字节,无所谓窄字符和宽字符。

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。