Charset与 Encoding区别

来源:互联网 发布:淘宝上的水弹枪合法吗 编辑:程序博客网 时间:2024/05/14 17:22

在绝大多数情况下,包括某些专业文章中,字符集和编码都统称为编码,这是因为一个字符集往往对应一种编码。但是在程序中,我们来不得半点马虎,我们应该清楚地知道字符集和编码有什么区别。以 ASP.NET 为例,Response.Charset 和 Response.Output.Encoding(只读)中的 Charset 和 Encoding 有什么区别呢?

Charset 是字符集,Encoding 是编码。

  • 字符集即字符的集合,规定了在这些集合里面有哪些字符,每一个字符都有一个编号(一个整数),但这只是编号不是编码。

  • 编码就规定了一个编号如何与二进制交互。

我们大多数人最先接触到的字符集是 1963 年的 ASCII,其中的每一个字符只需要用一个字节来表示就可以了。但世界上有许多种语言,像亚洲文字,比如中文,常用汉字就几千个,仅用一个字节来表示显然是不够的,假如我们使用两个字节。

那么问题就来了,为什么我们要把两个字节看成是一个汉字的编号呢?为什么我们不把两个字节看成 ASCII 字符集的两个编号呢?为了解决此问题,就得使用编码来标识了。

还有一个问题,编号(整数)1234 在字符集 A 中代表“千”,1234 在字符集 B 中代表“一”,那么 1234 究竟代表什么字呢?这就得明确字符集了。

浏览器可以自动识别使用哪个字符集,一般说来它们使用 HTTP 头部的 Content-Type 标明的字符集,如果没有向 HTTP 头部发送该信息,一般参考使用 HTML 的 head 标签中的 <meta http-equiv="Content-Type" content="text/html; charset=gb2312" />,为什么是参考使用呢?因为现在浏览器都比较聪明,如果发现这里用错了,一般会给予纠正。

我们做网页时,如果指定的 Charset 是 GB2312,那么就不应该在网页中出现繁体字,因为 GB2312 标准只有几千个简体的中文字。如果我们的网页编码是 UTF-8,我们就不要指定字符集是 GB2312,因为虽然 UTF-8 编码对应的 UTF-8 字符集包含了 GB2312 的字符,但同一个字符在两个字符集中的编号不一样。

对于我们中文简体网页,一般来说有两种搭配:

  • 一种是字符集是 GB2312,编码使用 ANSI。占用磁盘空间最少,网络传输效率最高。
  • 一种是字符集是 UTF-8,编码使用 UTF-8。虽然占用磁盘空间大,传输效率略低,但因为兼容面广,在应用 Ajax 以及包含多种语言文字时使用方便。鉴于此原因,现在许多网页开发工具都默认使用 UTF-8 来保存网页,比如要谈编码就要先谈两个十分容易混淆的概念,一个是编码字符集 (Coded Character Set),一个是字符编码方案 (Character Encoding Scheme)。

编码字符集就是将字符集中每个字符赋一个数字代码 ,这是为了便于计算机处理。编码字符集一般由标准组织制定,Unicode就是典型的编码字符集。一个编码字符集必定对应一个字符集,Unicode编码字符集对应Unicode字符集,那么什么是字符集呢?


字符集是一个字符的集合,它规定这个集合包含哪些字符 。Unicode字符集包含所有Unicode字符,这几乎囊括了世界上所有语言的文字。一个更小的字符集是ASCII字符集,它只有128个字符,包含 52个字母、10个数字、一些标点符号和一些控制字符。一个字符集想要被计算机表示,首先要将它映射成数字代码,因为计算机本质上只能表示数字,这是由编 码字符集定义的。如何存储这些数字代码就涉及到字符编码方案了。

字符编码方案定义如何将数字代码映射成字节序列 。有人可能就要问了,有必要这么麻烦吗,代码1不就映射成字节1,代码2不就映射成字节2,依次类推。的确如果,字符集的不超过256个字符,这是一种非 常合理简单的编码方案,每个字符只用一个字节来表示就可以了。但是如果字符集大小超过256个且不超过65536个,每个字符就需要2字节来编码,如果字 符集包含更多的字符就需要使用更多的字节来编码一个字符,这种编码方案称为定长编码 ,例如GB2312就是采用这样的编码方案。这种编码方案很简单但是却存在问题,它对常用的和生癖的字符都使用同样的长度来编码,这很浪费存储空间,一种更好的编码方案是使用变长编码 ,它对常用的字符使用一个字节来编码,对不常用的字符使用两个字节来编码,而对非常生癖的字符使用三个或更多的字节来编码。Unicode编码字符集的一 种变长编码方案是就是UTF-8,它的定长编码方案称为UTF-16。需要注意的是,既然涉及到多个字节就需要注意字节序了,因此UTF-16又分为 Big Endian UTF-16和Little Endian UTF-16。UTF-8只能有一种字节序,这是因为字符编码之后的字节之间存在依赖关系。

最后什么是编码呢?编码是编码字符集和字符编码方案的一个组合 ,它可以将字符集中的字符映射成字节序列。编码隐含着编码字符集和字符编码方案,从而也隐含着字符集。例如UTF-8是一种编码,它是Unicode编码 字符集和UTF8编码方案的一个组合。GB2312也是一种编码,它的编码字符集就是编码的简体中文字符集,编码方案采用定长编码。实践中经常混用编码字 符集和编码这两个概念,这是因为大多数编码字符集都只有一种编码方案,这样的编码字符集(或者说编码)包括GB2312, GBK, ASCII, ISO8859-1等。但是当编码字符集存在多种编码方案时,就有必要区分编码字符集和编码了,例如我们说Unicode时一般是指编码字符集,说 UTF-8,UTF-16时才是指编码。

编码就是 索引键,索引键对应了字符
字符集就是 一张键值表

不同的字符集会有不同的索引键派分方式

例如
1 在 A 字符集内对应了 a
1 在 B 字符集内对应了 b
如果用A字符集写入,读取时却说它是B字符集那么应该显示成a的东西就变成了b。
如果 1 在 B 字符集内是“乱码”,那么这个时候应该显示成a的东西就变成“乱码”了。