字符集与编码理解

字符集的概念其实区别于编码的概念,而我们有时候却把他们混淆一谈,因为对于不同的字符集与编码就是一个东西,说一样也确实没有什么问题,所以导致大家对这两个概念的混淆。

字符集与字符集编码是两个不同层面的东西

  • charset 是character set的简写,即字符集
  • encoding是charset encoding 的简写,即字符集编码

接口与接口实现的对比

从这里可以很清楚地看到

1、编码是依赖于字符集的,就像代码中的接口实现依赖于接口一样

(1)字符集就是有序的编号与字符的一一对应,编码其实就是将这个编号转换为计算机的具体存储方式,具体的计算机存储的二进制在根据编码规则就可以反转回(解码)字符集代表的编号。

2、一个字符集可以有多个编码实现,就像一个接口可以有多个实现类一样。(一个字符集可以对应多种计算机保存编码的方式或者规则,但是他们都是基于同一个字符集来进行编码)

3、通过上图,我们可以看到对于unicode字符集有utf-8、utf-16、utf-32三种编码,而对于ASCII、GBK他们的字符集即对应编码,这也就是我们有时候会混淆的原因。

具体例子及规范用法

可以看两个简单的例子,一个来自与html文件,用的是charset:

<meta http-equiv="content-type" content="text/html;charset=utf-8">

另一个是来自于xml文件,使用的是encoding:

<?xml version="1.0" encoding="UTF-8"?>

哪一个更加规范呢?通过上面的解释,相信大家心里都有一个答案了,那就是使用encoding。encoding表示具体的编码方式,及文件存储文字的方式。软件运行时根据具体的编码方式进行解码,转换为程序在内存中具体使用的字符集,这样程序才会认识我们的字符。(其实我们的字符在内存中也有具体的编码方式,这就看我们的系统或者软件允许时使用的字符集编码了)

“charset=utf-8”容易让人误解为存在一种叫“UTF-8”的字符集,但实际上,无论是 UTF-8,UTF-16 还是 UTF-32 都是对同一种字符集的不同编码实现而已。

为什么要严格区分字符集与编码这两个概念?

在早期,字符集与编码是一对一的,但随着时间的发展,出现了一对多的情形。

字符集与编码一对一的情形

有很多字符编码方案,一个字符集只有唯一一个编码实现,两者一一对应的。比如GB2312,这种情况,无论你怎么去称呼它们,比如“GB2312编码”,“GB2312字符集”,其实都说的一个东西,可能它本身就没有特意去做什么区分,无论怎么说都不会错。

字符集与编码一对多的情形

事情到了 Unicode 这里,变得不一样了,唯一的 Unicode 字符集对应了三种编码:UTF-8,UTF-16,UTF-32。如果还是这么笼统地去称呼,就很容易搞混了。

为什么Unicode这么特殊

人们弄出新的字符集,驱动力无外乎就是原来的字符集字符不够用了,不然谁会闲得蛋疼~~

 

Unicode的目标是统一所有的字符集,囊括所有字符,所以字符发展到它这里就到头了,再去整什么新的字符集就没必要也不应该了。

但如果觉得它现有的编码方案不太好呢?在不弄出新的字符集的情况下,那么就只能在编码方面上做文章了,于是就有了多个实现,这样一来,传统的一一对应关系就打破了。

我们严格区分字符集与编码的概念,理由就在这里。

指定了编码,它所对应的字符集自然就指定了,编码才是我们最终要关系的。

Unicode的早期与现在的对比

让我们来看一个图,它展现了Unicode早期与现在的一些差别:

 

注:由于历史方面的原因,你还会在不少地方看到把 Unicode 和 UTF-8 混在一块的情况,这种情况下的 Unicode 通常就是 UTF-16 或者是更早的 UCS-2 编码

下面是记事本程序保存时的一个截图,是Unicode的一个不规范使用,这里的Unicode就是指UTF-166:

我们现在说了不少 Unicode,由于各种原因,必须承认,在不同的语境下,“Unicode”这个词有着不同的含义,它可能指:

  • Unicode 标准
  • Unicode 字符集
  • Unicode 的抽象编码(编号),也即码点(code point)。
  • Unicode 的一个具体编码实现,通常即为变长的 UTF-16(16 或 32 位),又或者是更早期的定长 16 位的 UCS-2。

参考自一位大神的文章~~字符集与编码(一)——charset vs encoding

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章