编码知识大杂烩

零、万物归宗

ASCII码 (American Standard Code for Information Interchange,美国标准信息交换代码),最原始最直观的表示方式,一个字节表示一个字符,一个字节=8位,那么一个字节就有256(2的8次方)种状态。这又分为标准ASCII和扩展ASCII,其中:

标准ASCII (十进制0~127) 使用一个字节中除去最高位以外的7 位来表示所有的大写和小写字母,数字0 到9、标点符号,以及在美式英语中使用的特殊控制字符。

Tips:标准ASCII中使用了一种简单的方法来检验代码在传送过程中是否出错,即奇偶校验,一个字节中的最高位就是奇偶校验位,一般分奇校验和偶校验两种。奇校验规定:正确的代码一个字节中1的个数必须是奇数,若非奇数,则在最高位添1;偶校验规定:正确的代码一个字节中1的个数必须是偶数,若非偶数,则在最高位添1。这种方法挺简陋,如果一个字节中有两位同时变了,就检验不出来了。

  这么看来标准ASCII码是够美国人用了,可是法国人、阿拉伯人不高兴了,不是还有后128位嘛,所以就有了扩展ASCII:

扩展ASCII (十进制128~256)  允许将每个字符的第8 位用于确定附加的128 个特殊符号字符、外来语字母和图形符号。

  可是问题又来了,虽说前128个大家都一样,可是后128个就不敢苟同了,比如130(二进制10000010)在法语编码中代表了é,在希伯来语编码中却代表了字母Gimel (ג),在俄语编码中又会代表另一个符号,而且亚洲人还没发话,我们的汉字该怎么表示?几万个汉字哪能用这256种码表示全。这就有了下面中国的标准GB2312:

一、一步一步来

1、GB2312

  每个汉字及符号用两个字节来表示,理论上可以表示256*256 = 65536 个符号。实际上它收录有6763个简体汉字,682个符号,共7445个字符;

优点:适用于简体中文环境,属于中国国家标准,通行于大陆,新加坡等地也使用此编码; 

缺点:不兼容繁体中文,其汉字集合过少。 

  接下来很显然,港台人不愿意了,所以:

2、GBK

  它完全向下兼容GB2312,算是对GB2312的内码扩展(理论上不是有65536种嘛),当然也是两个字节表示一个符号。收录有21003个汉字,883个符号,共21886个字符; 

优点:适用于简繁中文共存的环境,为简体Windows所使用,向下完全兼容gb2312,向上支持 ISO-10646 国际标准 ;所有字符都可以一对一映射到Unicode2.0上; 缺点:不属于官方标准,和Big5之间需要转换;很多搜索引擎都不能很好地支持GBK汉字。

  就算考虑了港台人,56个民族没有考虑到的还有太多,终于,发了个大招:

3、GB18030

  用4个字节来表示一个符号,理论上足够了;收录了27484个汉字,同时收录了藏文、蒙文、维吾尔文等主要的少数民族文字。  优点:可以收录所有你能想到的文字和符号,属于中国最新的国家标准;  缺点:目前支持它的软件较少。

二、梦想还可以更大

0、Unicode字符集

如果有一种编码,将世界上所有的符号都纳入其中,每一个符号都给予一个独一无二的编码,那么乱码问题就会消失,这就是Unicode。

  需要强调的是,Unicode是字符集,而UTF-8、UTF-16、UTF-32是Unicode字符集的三种实现方式。    

1、UTF-8

  它是一种变长的编码方式,它可以用1~4个字节表示一个符号,根据不同的符号而变化字节长度。

  如图:UTF-8编码非常简单。如果一个字节的第一位是0,则这个字节单独就是一个字符;如果第一位是1,则连续有多少个1,就表示当前字符占用多少个字节。可以看出,比如对于英文字母a,UTF-8跟ASCII码的表示是一样的,所以UTF-8兼容ASCII码。

Tips1: UTF-8编码适用于网络数据传输,前缀码能让程序员很方便地用遍历的方法定位一段网络传输过来的字符串中出问题的字符,而不会影响到其他字符,保持能显示部分最大化,这对那些工作在较差网络环境下时很有利。而那些所有非前缀多字节编码在这种场合下最后的结果都是必须丢弃从出错点开始到结尾的所有编码,无论是GB码还是Unicode/UTF-16。

Tips2: UTF-8表示一个英文字符需要1个字节,而表示中文里我们常用到的汉字都需要3个字节。所以英文网站多是用UTF-8,而我们中文网站多是用GB码,我看腾讯、网易用的是GB2312。

2、UTF-16

  它也是变长的,可以用2个字节或者4个字节来表示一个符号。Windows系统下的Unicode方式默认就是指UTF-16。

Tips1: Windows NT内核的字符表示为UTF-16 little endian。为什么呢?我自己的理解是:首先Unicode字符集全球通用,其次用UTF-8编码解码,我们的程序需要不断去处理那些前缀码的逻辑,效率较低。而对于UTF-16,大多数字符都可以用两个字节来表示,处理起来so easy。

3、UTF-32

  是定长的,用4个字节表示一个符号,就空间而言,是非常没有效率的,使用也很少,就不讨论了。

4、文件用的哪种呢

  要知道具体是哪种编码方式,需要判断文本开头的标志,下面是所有编码对应的开头标志:

开头标志 编码方式

  EF BB BF    UTF-8   FE FF      UTF-16, little endian   FF FE      UTF-16, big endian   FF FE 00 00  UTF-32, little endian.   00 00 FE FF  UTF-32, big-endian.

  关于表中的big endian 和 little endian,举个例子,以汉字"严"为例,Unicode码是4E25,需要用两个字节存储,一个字节是4E,另一个字节是25。存储的时候,4E在前,25在后,就是big endian方式,也就是第一个字节在前;25在前,4E在后,就是little endian方式,也就是第二个字节在前。让我联想到我们汉语里的姓名就是big endian,而英语则是little endian,:) 

 三、还在发展

  最后,上一张维基的图,展示下字符编码的发展历程,全是人类智慧的结晶啊,应该也少不了斗争。

就这些吧,以后有收获了再补充。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏鹅厂优文

Python 工匠:编写条件分支代码的技巧

我一直觉得编程某种意义是一门『手艺』,因为优雅而高效的代码,就如同完美的手工艺品一样让人赏心悦目。

1.1K10
来自专栏数据小魔方

左手用R右手Python系列——面向对象编程基础

面向对象编程是程序设计中一种重要且高效的编程规范,它区别于常见的面向过程编程。在R语言以及Python的程序包开发过程中,大量使用了面向对象的编程范式。 百度...

51712
来自专栏阿凯的Excel

让你眼花缭乱的匹配函数反查技巧

小编已经连续写了三期关于匹配函数的用法,匹配函数的扛把子(老大)肯定是Vlookup函数莫属,但是Vlookup函数有一个问题,就是要查找的内容,必须在查找内容...

2966
来自专栏九彩拼盘的叨叨叨

如何给函数取个合适的名字

Quora 和 Ubuntu Forums thread 上的 4500 个程序员对上面的问题进行投票。49%的程序员认为给函数,变量等命名是最难的任务。

712
来自专栏玄魂工作室

如何学Python 第十八课 位运算符介绍

欢迎回来! 在我们上一次的培训课程中,我们介绍了类以及OOP如何使编程/脚本更容易。 今天我们将休息一下,并且介绍一些相当简单的按位运算符。 按位运算符相对简单...

3365
来自专栏嵌入式程序猿

号外号外:无规矩不成方圆(4)

本文MISRA规则由嵌入式程序猿整理自网络,版权归原作者所有 不能使用三字母词 三字母词由2 个问号序列后跟1 个确定字符组成(如, ??- 代表“ ~”(非)...

2685
来自专栏Spark学习技巧

Flink DataStream编程指南

Flink程序是执行分布式集合转换(例如,filtering, mapping, updating state, joining, grouping, defi...

1.9K7
来自专栏ASP.NETCore

.Net Core中使用ref和Span<T>提高程序性能

其实说到ref,很多同学对它已经有所了解,ref是C# 7.0的一个语言特性,它为开发人员提供了返回本地变量引用和值引用的机制。 Span也是建立在ref语法...

1585
来自专栏Java爬坑系列

【JAVA零基础入门系列】Day3 Java基本数据类型

  前两篇已经将开发环境搭建完成,如果你已经按之前的教程按部就班的完成了部署,那么世界上最优秀的编程语言之一和世界上最优秀的IDE之一已经出现在你的电脑上(此处...

2188
来自专栏Phoenix的Android之旅

你不知道的Interface的骚操作

"难道面试不顺利?"小A心想。于是问小呼都问了什么。小呼说,面试官问了个奇怪的问题,

732

扫码关注云+社区

领取腾讯云代金券