编码字符集与字符集编码


常说的字符集和编码区别,其实就是编码字符集和字符集编码的区别,其实,单单若是只是说字符集,没有任何编码的概念的话,那么字符集其实仅仅是一个简单的字符的集合,或者说是一个抽象的字符的集合,包括文字,符号等等,不参与任何存储形式,只是存在这么各类各样标准的字符的集合html

若是仅仅是抽象的字符集,咱们是无需拿出讨论的,由于没有任何异议,通俗易懂,而常说的字符集指的编码字符集,好比常见的 unicode、ascii、gb23十二、gbk等,这些咱们常称作为字符集(实际上是编码字符集),这些字符集,好比unicode其实本质上是已经“编码”过的字符集,即每一个字符都有惟一的整数编号,每一个字符都有本身特有的编号,同一个字符在不一样编码字符集中编号也会不一样,固然不少编码字符集都是ascll的超集,因此ascll字符集的编号与不少编码字符集中编号都同样,好比英文字母“A”,在ASCII及Unicode及GB2312中,均是第0x41个字符,说到这里朋友必定注意到了我上面再描述“ unicode其实本质上是已经“编码”过的字符集”中的“编码”二字加了双引号,我要强调的是这里的“编码”并非真的我下面要说的编码,这里只是为每一个字符编了一个对应的编号,可是咱们仍是习惯专业的称呼为“编码字符集”面试

咱们常常说“文章采用的是utf-8编码方式”浏览器

我对于这个编码方式的意义,我的理解是 将一个字符的整数编号用一个什么二进制的整数值来对应并在计算机存储这和上面说的编码字符集中的“编码”千差万别,这里咱们称之为“字符集编码”,即咱们常说的编码post

说到这里,不少人会以为那么unicode和utf-8的区别在哪里?既然上文说到unicode是编码字符集,那么utf-8又是什么?就是常说的编码?编码

“文章采用的是utf-8编码方式”,我的以为准确的说法是“文章采用的是基于unicode编码字符集的utf-8的编码方案”,即spa

即unicode自己做为编码字符集没有任何存储形式,只是一个编号和字符对应的表而已,如何在计算机存储?你可能想到了干脆直接把编号看成二进制数值来直接存储,那么为何不这么作呢?这也算是一种字符集编码方案,就是基于unicode编码字符集的utf-32编码方案,那么有没有更加智能一点的编码方案呢?为何会没有呢?那就是utf-八、utf-16等等,    等等,在我解释为什么要用utf-8编码方案的时候,我必须说明一件事情:以下操作系统

我在上一篇文章《你不知道的 页面编码,浏览器选择编码,get,post各类乱码由来》中说过:“如何查看中文字符的十六进制字符串?方法:BitConverter.ToString(System.Text.Encoding.UTF8.GetBytes("阿道夫"));” 请注意我能够改成“System.Text.Encoding.Unicode.GetBytes” 以下图是vs2013 Encoding键入“.”后的智能提示code

  (列表过长,用两幅图分别截图)htm

上图有两个疑问:blog

一、若是说unicode是编码字符集,为什么会出如今和utf-8这种编码方案并列的列表中?

二、ASCII或者gb2312都是编码字符集为什么也会出如今和utf-8这种编码方案并列的列表中?

咱们假设有两个猜想:

一、此处的unicode并非真正的unicode编码字符集,可能只是一种和unicode编码字符集关系很是紧密的一种编码方案

二、ASCII或者gb2312(其实就是图中的Default,即操做系统当前的编码,国内通常为gb2312)是编码字符集没有错,可是对于ASCII或者gb2312都只有惟一一种编码,那么我称呼它们为ASCII编码或者GB2312编码也没有问题,既然这样,那我把ascii和gb2312加入和utf-8这种编码方案并列的列表中也理所固然?

个人两个假设,很快获得论证

一、在Encoding 的元数据看到:

复制代码
1         //
2         // 摘要:
3         //     获取使用 Little-Endian 字节顺序的 UTF-16 格式的编码。
4         //
5         // 返回结果:
6         //     使用 Little-Endian 字节顺序的 UTF-16 格式的编码。
7         public static Encoding Unicode { get; }
复制代码

这里解释在这里的unicode其实本质上“获取使用 Little-Endian 字节顺序的 UTF-16 格式的编码”,即便基于unicode编码字符集的utf-16编码方案,相似的有BigEndianUnicode(获取使用 Big Endian 字节顺序的 UTF-16 格式的编码)
二、通常的ASCII或者gb2312,咱们能够称呼为ASCII字符集也能够称呼为ASCII编码,只是意义不一样而已,由于对于ASCII编码字符集或者gb2312编码字符集都只有惟一一种编码,就是ASCII编码和GB2312编码,那么列表中显示的ASCII和GB2312指的不是编码字符集而是ASCII和GB2312的编码方案,我想正是这种缘由,才在不少时候,不论是字符集赋值仍是编码方案赋值均可以直接用gb2312或者ascii,好比:
Encoding gb2312 = Encoding.GetEncoding("gb2312");
Response.ContentEncoding = gb2312;//编码
Response.Charset="gb2312";//字符集

总结下的说:
就是unicode是字符集,不是编码!可是ascii(gb2312)是字符集,这个说法确定正确,可是我表达为“ascii编码”也不能说大错特错,可是这种说法让人误解,若是必定要说那么就说“ascii编码字符集的编码”

若是理解上面两个假设的论证道理,那么咱们继续讨论以前暂停的话题,即“解释为什么要用utf-8等编码方案(其余utf编码方案相似)”
utf-8将很大一部分基于unicode编码字符集的字符的整数编号做了变换后存储在计算机中。(引用)以“汉”字为例,“汉”的Unicode值为0x6C49,但其编码为UTF-8格式后的值为0xE6B189(注意到变成了三个字节)。对于UTF-16编码方案,则是对unicode编码字符集中的前65536个字符编号都不作变换,直接做为计算机存储时使用的值(对65536之后的字符,仍然要作变换),例如“汉”字的Unicode编号为0x6C49,那么通过UTF-16编码后存储在计算机上时,它的表示仍为0x6C49,对于UTF-32编码方案,他对全部的Unicode字符均不作变换,直接使用编号存储,只是这种编码方案太浪费存储空间(就连1个字节就能够搞定的英文字符,它都必须使用4个字节)

既然unicode编码字符集有如此多的编码方案,那么
utf-8,字母数字符号等占1字节,汉字占三字节
utf-16,对unicode编码字符集中的前65536个字符都占两个字节
utf-32,所有占四字节

若是还有人问:
“unicode编码每一个字符占几个字节”,咱们能够义正词严的说,第一unicode不是编码!第二每一个字符具体占多少字节是要看编码方案!

不少面试题会问:

1 string param = "abc阿道夫";
2 int length1 = System.Text.Encoding.Unicode.GetBytes(param).Length;//别忘了这里的unicode本质是utf-16编码方案
3 int length2 = param.Length;

那么答案就是12和6了最后,对于gb2312或者ascii编码字符集的字符的编号就是直接存储在计算机中的二进制数,也就是说gb2312和ascii编码字符集都只有一种编码方案,由于在gb2312编码字符集中的ascii字符集部分的编号并无变化(即和ascii编码字符集中的编码一致),因此gb2312的ascii部分字符存入计算机的二进制数仍是占用1个字节,而中文字符存入计算机的二进制数也是该中文字符在gb2312编码字符集中的编号,该编号通常转换成二进制数都占两个字节,这个过程也就变成了所谓的gb2312编码若是上面的改成System.Text.Encoding.Default.GetBytes(param).Length,则值就是9和6了