unicode、utf-8、ansi、gbk、gb2312编码详解


ascii

ASCII (American Standard Code for Information Interchange):美国信息交换标准代码是基于拉丁字母的一套电脑编码系统,主要用于显示现代英语和其他西欧语言。它是最通用的信息交换标准,并等同于国际标准 ISO/IEC 646。ASCII第一次以规范标准的类型发表是在1967年,最后一次更新则是在1986年,到目前为止共定义了128个字符

很久以前,计算机制造商有自己的表示字符的方式。他们并不需要担心如何和其它计算机交流,并提出了各自的方式来将字形渲染到屏幕上。随着计算机越来越流行,厂商之间的竞争更加激烈,在不同的计算机体系间转换数据变得十分痛苦,人们厌烦了这种自定义造成的混乱,于是就有人站出来阻止这种混乱,他振臂高呼,组织各大厂商开始统一编码,与秦始皇统一文字与异曲同工之妙,他们用一个字节来表示他们使用的字符,a,b,c,d什么的,实际上他们只用了128个,其中0~31是控制字符,32~127是可显示字符,这就是后来的ascii编码了:

但是啊,这些老美万万没想到,计算机是如此的受人欢迎,很快计算机就在其它国家流行开了,其它国家看有很多本土常用的字符,ascii中没有,于是就有人想啊,一个字节中不是才用了一半吗,这不最高位还没用吗,于是各个国家就开始用最高位来扩展ascii以便能够表示自己国家的一些字符,但是这并不是对每个国家都有效的,特别是我们的大天朝,你英文就那几个,但是我们文化博大精深啊,我们的汉字那可就有好几万个,你就给我一个字节,我怎么玩?


gb2312、big-5与gbk

一个字节要表示我国那么多中文,是万万办不到的,那么就只好再加一个字节了:
我们不客气地把那些127号之后的奇异符号们直接取消掉, 规定:一个小于127的字符的意义与原来相同,但两个大于127的字符连在一起时,就表示一个汉字,前面的一个字节(他称之为高字节)从0xA1用到0xF7,后面一个字节(低字节)从0xA1到0xFE,这样 我们就可以组合出大约7000多个简体汉字了。在这些编码里,我们还把数学符号、罗马希腊的字母、日文的假名们都编进去了,连在 ASCII 里本来就有的数字、标点、字母都统统重新编了两个字节长的编码,这就是常说的"全角"字符,而原来在127号以下的那些就叫"半角"字符了。 中国人民看到这样很不错,于是就把这种汉字方案叫做 "GB2312"GB2312 是对 ASCII 的中文扩展

但是,你以为这样就够用了吗?当然不行,gb2312能够表示很多简体汉字,但是繁体怎么办呢?台湾群众很不满啊,于是也自己搞了一套编码,于是big-5诞生了,你以为这样就完了?gb2312仅仅可以表示6000多个常用汉字你让其它不常用的怎么办?于是扩展呗,把之前gb2312中没有利用的位好好利用起来,就成了gbk,这又增加了20000多个汉字,但是咱们少数名族也要用电脑啊,于是有了后来的 GB18030

GB2312和GBK都是用两个字节来编码的,就算用完所有的位(256*256=65536)也不够为所有的汉字编码。于是就有了目前最新的GB18030,它采用类似UTF-8的编码方式进行编码(每个字符的编码可以是 1、2或4个字节),拥有上百万个编码空间,足以支持中日韩三国所有汉字,并且还可以支持国内少数民族的文字。

GB2312是一个字符集,全称“信息交换用汉字编码字符集”(GB是“国标”的拼音缩写,2312是国标序号),包含6763个汉字;GB码共收录6763个简体汉字、682个符号,其中汉字部分:一级字3755,以拼音排序,二级字3008,以偏旁排序。
GBK也是一个字符集,是GB2312的扩充(K是“扩”的拼音缩写),包含21003个汉字,兼容GB2312(也就是说这21003个汉字是包括GB2312的6763个汉字的)。
通常把这6763字称为“常用字”,而将包含在GBK而不包含在GB2312字符集内的汉字称为“生僻字”,如果要使用QQ五笔或极点五笔打生僻字,需要切换(默认快捷键Ctrl+M)

但是这毕竟是属于一种“方言”式的编码,很多其它国家是不懂你这个编码的,于是各种编码的出现又导致了混乱,于是unicode闪亮登场了!


unicode与utf-8

在这之前我们需要先理清个概念:
Unicode只是简单的字符到数字的一个映射,就相当于一个电话本,它是没有字节限制的,是可以无限表示的,它也不管一个字符在计算机中式怎么存储的,具体怎么存储涉及到字符编码,而unicode应该叫做字符集

Unicode为世界上的每一个字符都弄了一个对应的数字,所以就不会再存在乱码问题了,比如,汉字“严”的 Unicode 是十六进制数 4E25 ,转换成二进制数足足有15位( 100111000100101 ),也就是说,这个符号的表示至少需要2个字节。表示其他更大的符号,可能需要3个字节或者4个字节,甚至更多,这里会出现几个问题:

  • 我们怎么知道是三个字节一起表示一个字符,还是说三个字节分别表示三个字符
  • 之前一个ascii字符只需要一个字节,但是现在用了unicode普遍使用三个或四个字节,那使用英文就会浪费很多字节

于是针对unicode出现了很多不同的编码方案,这些方案就是为了解决unicode在计算机中具体怎么存储的问题,经常听说的有:utf-8、utf-16、utf-32

  • utf-16是用两个或四个字节表示一个字符
  • utf-32使用四个字节表示一个字符
  • 而utf-8是可变长的编码方案,它可以用1~4个字节表示不同字符,显而易见,前面两种编码方案会浪费很多字节,而utf-8就很好了,所以我们现在也通常使用utf-8

那utf-8具体是怎么编码unicode的呢?

  • 对于单字节的符号,字节的第一位设为 0 ,后面7位为这个符号的 Unicode 码。因此对于英语字母,UTF-8 编码和 ASCII 码是相同的。
  • 对于n 字节的符号( n > 1 ),第一个字节的前 n 位都设为 1 ,第 n + 1 位设为 0 ,后面字节的前两位一律设为 10 。剩下的没有提及的二进制位,全部为这个符号的 Unicode 码。

根据utf-8的编码规则,我们就可以发现它很好的解决了前面的两个问题:兼容ascii且不适用多余的字节;多字节的字符,我们可以通过判断它的第一个字符来确定字节数。
这是一份编码表,其中xxx处填写相应的unicode值

Unicode符号范围(16进制)   	|	UTF-8编码方式(二进制)
----------------------------|---------------------------------------------
0000 0000 - 0000 007F  	    |	0xxx xxxx
0000 0080 - 0000 07FF	    |	110x xxxx  10xx xxxx
0000 0800 - 0000 FFFF	    |	1110 xxxx  10xx xxxx  10xx xxxx
0001 0000 - 001F FFFF	    |	1111 0xxx  10xx xxxx  10xx xxxx  10xx xxxx

举个例子:
“侠”的unicode表示是4fa0,根据上表我们来计算一下它的utf-8编码:
根据上表,4fa0在第三行的位置,也就是我们需要把unicode值依次填入1110xxxx 10xxxxxx 10xxxxxx中,开始填字游戏吧:
11100100 10111110 10100000
转换为16进制后:E4BEA0


UTF-8编码使用的字节从1到4不等

  • 前128个与ASCII字符重合的码点(U+0000~U+007F)使用1字节表示
  • 带变音符号的拉丁文、希腊文、西里尔字母、阿拉伯文等使用2字节来表示
  • 而东亚文字(包括汉字)使用3字节表示
  • 其他极少使用的语言的字符则使用4字节表示。

ansi又是什么?

ANSI是一种字符代码,为使计算机支持更多语言,通常使用 0x00~0x7f 范围的1 个字节来表示 1 个英文字符。超出此范围的使用0x80~0xFFFF来编码,即扩展的ASCII编码。

其实ANSI并不是某一种特定的字符编码,而是在不同的系统中,ANSI表示不同的编码。你的美国同事Bob的系统中ANSI编码其实是ASCII编码(ASCII编码不能表示汉字,所以汉字为乱码),而你的系统中(“汉字”正常显示)ANSI编码其实是GBK编码,而韩文系统中(“한국어”正常显示)ANSI编码其实是EUC-KR编码

话说计算机是由美国佬搞出来的嘛,他们觉得一个字节(可以表示256个编码)表示英语世界里所有的字母、数字和常用特殊符号已经绰绰有余了(其实ASCII只用了前127个编码)。后来欧洲人不干了,法国人说:我需要在小写字母加上变音符号(如:é),德国人说:我也要加几个字母(Ä ä、Ö ö、Ü ü、ß)。于是,欧洲人就将ASCII没用完的编码(128-255)为自己特有的符号编码(后来称之为“扩展字符集”)。等到我们中国人开始使用计算机的时候,尼玛,256个编码哪够?我泱泱大中华,汉字起码也得N多万吧,就连小学生都得要求掌握两三千字。国标局最后拍板:一个字节不够,那我们就用多个字节来为汉字编码吧,但是,国情那么穷,字节那么贵,三个字节伤不起,那就用俩字节吧,先给常用的几千汉字编个码,等以后国家强盛了人民富裕了,咱再扩展呗---于是GB2312就产生了。台湾同胞一看,尼玛,全是简体字,还让不让我们写繁体字的活了,于是台湾同胞也自己弄了个繁体字编码---大五码(Big-5)。同时,其它国家也在为自己的文字编码。最后,微软苦逼了:顾客就是上帝啊,你们的编码我都得满足啊,这样吧,卖给美国国内的系统默认就用ASCII编码吧,卖给中国人的系统默认就用GBK编码吧,卖给韩国人的系统默认就用EUC-KR编码,...但是为了避免你们误会我卖给你们的系统功能有差异,我就统一把你们的默认编码都显示成ANSI吧。---本故事纯属虚构,但“ANSI编码”确实只存在于Windows系统

windows系统通过Windows code pages的值来确定当前系统的编码方式。


参考资料

unicode、utf-8、ansi、gbk、gb2312编码详解

ansi是什么编码

阮一峰的解释

中文字符的几种编码

细说:Unicode, UTF-8, UTF-16, UTF-32, UCS-2, UCS-4

国外比较好的一篇文章(推荐)

posted @   guanyubo  阅读(1405)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· DeepSeek “源神”启动!「GitHub 热点速览」
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· 我与微信审核的“相爱相杀”看个人小程序副业
· C# 集成 DeepSeek 模型实现 AI 私有化(本地部署与 API 调用教程)
· spring官宣接入deepseek,真的太香了~
点击右上角即可分享
微信分享提示