工作中系统的乱码问题经常让人头疼,看到utf-8,GBK等字样觉得很熟悉,却一直对这些概念一知半解。所以今天简单梳理下字符集编码的内容,方便以后查阅。
先来说说为什么要有字符集和编码。在计算机中都只能存储0和1,所以要让计算机能识别某个字符并存储和传输,就必须用二进制来表示。字符集和编码就是为了把字符唯一标识成计算机可以识别和存储的二进制而定义的编码映射集合和编码规则。
一、概念
1. 字符集charset
按字面理解就是字符的集合。但一般指的是定义了字符和其对应的二进制代码的映射关系的集合。为了方便阅读,二进制代码是用十六进制来表示。例如:符号“A” 对应的代码是 0X65.
我查阅了网上很多文章,两种理解都有。但是我更倾向于按第二种理解方式。因为单纯的定义字符的集合是没有意义的,字符有了对应的二进制代码才能在计算机中存储和使用。常见的字符集有ASCII,GBK, unicode等等。
2. 字符集编码 encoding:
定义了字符如何在计算机中存储的规则。在字符集中只是定义了字符对应的代码,这个代码要在计算机中落地,还要考虑对空间的占用,使用的效率,传输的容错等等因素,来决定编码的规则。
如果把字符集定义的代码原样存储,那么该字符集就只有一种字符集编码,所以这种情况就不严格区分字符集和字符编码。例如GBK既表示字符集,也可以表示字符集编码。目前来看只有unicode字符集有不同的编码UTF-8,UTF-16,UTF-32。
二、字符集发展历程
字符集最早是美国定义的ASCII码,所以主要只考虑了英文字母和符号,一共128个字符,所以使用7位bit就可以表示。后面由于欧洲中国等文字的需求,就逐步扩展建立了不同的标准,不过都是向下兼容ASCII。
windows中选择字符集有一个是ANSI,其实这不是字符集,这个表示采用当地默认的字符集,如果是中国大陆就是GB2312,台湾就是BIG5,英文地区就是ASCII
三、字符编码规则
只有unicode的编码比较复杂,所以详细介绍UTF8的编码。
如果只占7个bit,那么第8位补0,即0xxxxxxx,兼容ASCII;
如果n个字节,那么高字节从高位开始,补n+1个bit,依次为n个1和0,其余字节补10xxxxxx。
小于8位,用1个字节表示,为 0xxxxxxx;
如果占位小于11位的,用2个字节表示,为110xxxxx 10xxxxxx;
大于11位小于18位的,用3个字节表示,为 1110xxxx 10xxxxxx 10xxxxxx。
如果需要进一步学习更详细的内容,推荐参考:
1. 阮一峰 《字符编码笔记:ASCII,Unicode 和 UTF-8》
http://www.ruanyifeng.com/blog/2007/10/ascii_unicode_and_utf-8.html
2. notbecoder 《字符集和字符编码》 这篇文章讲的四层编码,我觉得有点复杂了。
https://www.cnblogs.com/notbecoder/p/4840783.html
四层编码
在计算机中,要建立一种“字符编码模型”,需要四步【4】。
1. 要有一个字符库,确定这些字符足够表意。 比如ASCII字符集,已经足够表示英语,但不能表示中文,于是产生GB2312字符集。
2. 第一层编码,给每个字符编个数字,英文叫Code Point 或 Code Position。比如ASCII字符集中,65表示“A”,97表示“a”。
3. 第二层编码,确定表示字符的二进制位数(8位,16位,32位)。ASCII使用7位,DBCS(双字节字符集)使用16位。
4. 第三层编码,确定字符二进制值的存储格式(大端法,小端法)。比如X86机器使用小端法。