ASCII、Unicode、UTF-8、UTF-16、GBK、GB2312、ANSI等编码方式简析
ASCII、Unicode、UTF-8、UTF-16、GBK、GB2312、ANSI等编码方式简析
序言
从各种字节编码方法中,能看到那个计算机发展的洪荒时期的影子。
ASCII
ASCII码有标准ASCII码和拓展ASCII码之分,这里分开讲解。
标准ASCII码
标准ASCII码占用一个字节,但是只用了后7位,第一位是0.一个字节本来可以表示256种不同情况,而由此ASCII码只有128种符号。这128种符号包括英文26字母的大小写、数字0-9、32个不可打印的控制字母、符号(就是我们在键盘上可以看到的符号)
附ASCII码表查询地址:http://ascii.911cha.com/
拓展ASCII码(EASCII,即Extended ASCII)表
拓展ASCII码依然是一个字节,只不过把空闲下来的第一位也用上了。EASCII码比ASCII码扩充出来的符号包括表格符号、计算符号、希腊字母和特殊的拉丁符号
Unicode和UTF-8
划重点:Unicode并不是一种具体的实现方式,而只是为所有的字符标记一个对应的数字,并不限制具体如何实现。而utf-8恰好是Unicode最广为应用的实现方法
UTF-8的编码规则如下:
1)对于单字节的符号,字节的第一位设为
0,后面7位为这个符号的 Unicode 码。因此对于英语字母,UTF-8 编码和 ASCII 码是相同的。2)对于
n字节的符号(n > 1),第一个字节的前n位都设为1,第n + 1位设为0,后面字节的前两位一律设为10。剩下的没有提及的二进制位,全部为这个符号的 Unicode 码。
根据这个规则,我们可以很轻易的解析出UTF-8的编码:如果一个字节的第一位是0,则这个字节单独就是一个字符;如果第一位是1,则连续有多少个1,就表示当前字符占用多少个字节。
UTF-8实现了对ASCII码的向后兼容,并且对于各种符号的不同字节长度表示都给予了支持,所以被称为可变长度编码。这有一个显著的好处,就是对于纯英文文档,我们依然可以用一个字节来表示所有的字符(要知道,如果只能用两个字节来表示的话,所有英文文档的大小将是用ASCII码表示的两倍,这个代价所示不可接受的)
所以,如果我们仅仅是说字符是由utf-8编码的话,我们是不知道它的字节占用情况的~
GB2312和GBK等
GB2312是一种用两个字节表示汉字的编码方法。它的全称是“中华人民共和国国家标准简体中文字符集“,由中国国家标准总局发布,1981年5月1日实施。
GBK是对GB2312-80的扩展.由于GB 2312-80只收录6763个汉字,有不少汉字,如部分在GB 2312-80推出以后才简化的汉字(如“啰”),部分人名用字(如中国前总理朱镕基的“镕”字),台湾及香港使用的繁体字,日语及朝鲜语汉字等,并未有收录在内。于是厂商微软利用GB 2312-80未使用的编码空间,收录GB 13000.1-93全部字符制定了GBK编码。
对于ASCII字符,gbk依然是用一个字符表示的,是兼容的
国家标准GB18030-2005《信息技术 中文编码字符集》是我国继GB2312-1980和GB13000-1993之后最重要的汉字编码标准.GB18030-2005的主要特点是在GB18030-2000基础上增加了CJK统一汉字扩充B的汉字。
目前使用较多的还是GBK和GB2312
ANSI
不同的国家和地区制定了不同的标准,由此产生了 GB2312、GBK、Big5、Shift_JIS 等各自的编码标准。这些使用 1 至 4 个字节来代表一个字符的各种汉字延伸编码方式,称为 ANSI 编码。
在简体中文Windows操作系统中,ANSI 编码代表 GBK 编码;在日文Windows操作系统中,ANSI 编码代表 Shift_JIS 编码。 不同 ANSI 编码之间互不兼容,当信息在国际间交流时,无法将属于两种语言的文字,存储在同一段 ANSI 编码的文本中。
由此可见,ANSI实际上指什么,有赖于操作系统的语言。这其实可以理解为微软(因为根据引用3所说,只有Windows系统使用ANSI编码)为了适应不同国家的编码方式的不同而想到的方法:在不同国家默认使用不同的编码方法,只是为了显示功能性的统一才起名为ANSI。个人认为这个是有点坑的设置····
那么ANSI的这个根据国家切换编码方式的功能是怎么控制的呢?
微软用一个叫“Windows code pages”(在命令行下执行chcp命令可以查看当前code page的值)的值来判断系统默认编码,比如:简体中文的code page值为936(它表示GBK编码,win95之前表示GB2312,详见:Microsoft Windows' Code Page 936),繁体中文的code page值为950(表示Big-5编码)。
这个code page也是可以控制的:
命令提示符下,我们可以通过chcp命令来修改当前终端的active code page,例如:
(1) 执行:chcp 437,code page改为437,当前终端的默认编码就为ASCII编码了(汉字就成乱码了);
(2) 执行:chcp 936,code page改为936,当前终端的默认编码就为GBK编码了(汉字又能正常显示了)。
上面的操作只在当前终端起作用,并不会影响系统默认的“ANSI编码”。
如果要修改全局的code page,就要设置当前系统区域(locate)
而对于Linux,其默认的编码方式是utf-8,如果我们在Windows下写好一个用ANSI编码方式(对于中国,其实就是GBK)写的文件,在Linux系统中打开,就会看到乱码。这时我们可以选择更改locale,即更换Linux的编码方式来解决问题,见图(图源引用3)

UTF-16LE 和UTF-16BE

这是记事本中的编码方式,还剩下UTF-16 LE和UTF-16 BE我们没有提到。
UTF-16
UTF-16是Unicode字符编码五层次模型的第三层:字符编码表(Character Encoding Form,也称为 "storage format")的一种实现方式。即把Unicode字符集的抽象码位映射为16位长的整数(即码元, 长度为2 Byte)的序列,用于数据存储或传递。Unicode字符的码位,需要1个或者2个16位长的码元来表示,因此这是一个变长表示。
UTF-16的出现时间比UTF-8早,但是相比UTF-8,它有几个显著的缺点:
- 不支持ASCII编码:由UTF-16的定义可以看出来,它的最短长度是16位,也就是2个字节,这就使得它无法兼容ASCII
- 相比UTF-8更费空间
现今UTF-16依然存在于计算机系统中是为了向下兼容,其本身用的已经不太多了(但也有应用,比如在JavaScript中,所有的string类型(或者被称为DOMString)都是使用UTF-16编码的),所以详细的编码方法这里就不说了。
LE 和BE是什么
LE是指低字节序(Little Endian),BE指高字节序(Big Endian),这里涉及到了一个很底层的问题:如果一个字符需要两个字节来表示,那么这两个字节应该怎么存储,是高位在前还是低位在前?这个问题在当初学习汇编语言时就曾给我造成疑惑,但当时的我并不知道这背后的故事。
Endian读作End-ian或者Indian。这个术语的起源可以追溯到格列佛游记。(小说中,小人国为水煮蛋应该从大的一端(Big-End)剥开还是小的一端(Little-End)剥开而争论,争论的双方分别被称为“大端派”和“小端派”。)
字节序方案只是一个微处理器架构设计者的偏好问题,例如,Intel使用低字节序,Motorola使用高字节序。
以汉字
严为例,Unicode 码是4E25,需要用两个字节存储,一个字节是4E,另一个字节是25。存储的时候,4E在前,25在后,这就是 Big endian 方式;25在前,4E在后,这是 Little endian 方式。
可以看到,BE方式和人类读写数值的方式是一致的,那为什么不直接用BE?
计算机电路先处理低位字节,效率比较高,因为计算都是从低位开始的。所以,计算机的内部处理都是小端字节序
我们可以注意到一个问题,上面图中为什么只有UTF-16有字节序问题,为什么ANSI和UTF-8没有字节序问题?不是因为UTF-16特别,是因为Unicode在制定标准的时候,并没有规定字节序,这就给UTF-16和UTF-32这样的以多字节为处理单位的编码方式埋了一个大坑,使得后代许多人都纠结在字节序转换的问题上。而UTF-8是以单字节为基本处理单位的
如果一个字符使用utf-8表示,就需要将这个字符的Unicode码,编码成字节数组,这里要注意“字节”“数组”这两个概念,所以对于字节数组写入内存时,只需要按照数组的顺序,一个一个字节写入,不存在高位和低位的问题。
而对于GBK,机智的标准制定者在标准中已经说明白了:

划重点:两个字节中前面的字节为第一字节,后面的字节为第二字节
如何处理字节序问题
有一个很巧妙的约定来解决UTF-16的字节序问题,它叫做BOM(字节顺序标记)。BOM放置在文档的开头,用来告诉阅读器这个文档的字节序是什么。如果是高字节序,就写入FE FF;如果是低字节序,就写入FF FE。
"带有BOM的UTF-8"又是什么?
UTF-8 不需要 BOM,尽管 Unicode 标准允许在 UTF-8 中使用 BOM。
所以不含 BOM 的 UTF-8 才是标准形式,在 UTF-8 文件中放置 BOM 主要是微软的习惯(顺便提一下:把带有 BOM 的小端序 UTF-16 称作「Unicode」而又不详细说明,这也是微软的习惯)。微软在 UTF-8 中使用 BOM 是因为这样可以把 UTF-8 和 ASCII 等编码明确区分开,但这样的文件在 Windows 之外的操作系统里会带来问题。例如UTF-8 的网页代码不应使用 BOM,否则常常会出错。
总结
这里附上一个很好用的表,便于涉及到对应的处理时进行查询(来源:引用10)
占用字节从小到大排序
- 英文字符
字节数 : 1;编码:GB2312
字节数 : 1;编码:GBK
字节数 : 1;编码:GB18030
字节数 : 1;编码:ISO-8859-1
字节数 : 1;编码:UTF-8字节数 : 2;编码:UTF-16BE
字节数 : 2;编码:UTF-16LE字节数 : 4;编码:UTF-16
- 中文字符
字节数 : 1;编码:ISO-8859-1
字节数 : 2;编码:UTF-16BE
字节数 : 2;编码:UTF-16LE
字节数 : 2;编码:GB2312
字节数 : 2;编码:GBK
字节数 : 2;编码:GB18030字节数 : 3;编码:UTF-8(大部分,很少部分需要4字节)
字节数 : 4;编码:UTF-16
Reference
- http://www.ruanyifeng.com/blog/2007/10/ascii_unicode_and_utf-8.html
- https://www.freebuf.com/articles/others-articles/25623.html
- https://www.cnblogs.com/malecrab/p/5300486.html
- https://www.zhihu.com/question/19677619
- https://zh.wikipedia.org/wiki/%E6%B1%89%E5%AD%97%E5%86%85%E7%A0%81%E6%89%A9%E5%B1%95%E8%A7%84%E8%8C%83
- https://juejin.im/post/5ace27c96fb9a028dc416195
- http://www.ruanyifeng.com/blog/2016/11/byte-order.html
- https://www.zhihu.com/question/62587928
- https://blog.csdn.net/a_little_a_day/article/details/78923071
10.https://blog.csdn.net/yaomingyang/article/details/79374209
ASCII、Unicode、UTF-8、UTF-16、GBK、GB2312、ANSI等编码方式简析的更多相关文章
- 字符编码和python使用encode,decode转换utf-8, gbk, gb2312
ASCII码 标准ASCII码使用7位二进制数表示大写或小写字母,数字0到9标点符号以及在美式英语中使用的特殊控制字符. 在标准ASCII码中,最高位(b7)用作奇偶校验位,所谓奇偶校验,是指在代码传 ...
- Unicode gbk gb2312 编码问题 [转载]
原文地址: http://www.cnblogs.com/csn0721/archive/2013/01/24/2875613.html HTML5 UTF-8 中文乱码 <!DOCTYPE ...
- UNICODE UTF编码方式解析
先明确几个概念 基础概念部分 1.字符编码方式CEF(Character Encoding Form) 对符号进行编码,便于处理与显示 常用的编码方式有 GB2312(汉字国标码 2字节) ASCII ...
- 【转】关于字符编码,你所需要知道的(ASCII,Unicode,Utf-8,GB2312…)
转载地址:http://www.imkevinyang.com/2010/06/%E5%85%B3%E4%BA%8E%E5%AD%97%E7%AC%A6%E7%BC%96%E7%A0%81%EF%BC ...
- UTF-8 GBK GB2312 之间的区别和关系
UTF-8:Unicode TransformationFormat-8bit,允许含BOM,但通常不含BOM.是用以解决国际上字符的一种多字节编码,它对英文使用8位(即一个字节),中文使用24为(三 ...
- 计算机编码方式详解(Unicode、UTF-8、UTF-16、ASCII)
整理这篇文章的动机是两个问题: 问题一: 使用Windows记事本的"另存为",可以在GBK.Unicode.Unicode big endian和UTF-8这几种编码方式间相互转 ...
- python - 2 8 16进制/颜色/字符编码
1.二进制 八进制 十六进制 二进制: bin() 0b10010八进制: oct() 0o10十进制: 1-100十六进制: hex() 0X53 BH 十进制转2, 8,16进制: >> ...
- 见到Unicode、GB2312、GBK 、ANSI、Ascii、DBCS、BIG5、UTF这一堆名词你是否犯晕?请看转载的好文
作者:于洋链接:https://www.zhihu.com/question/23374078/answer/69732605来源:知乎著作权归作者所有.商业转载请联系作者获得授权,非商业转载请注明出 ...
- ASCII,unicode, utf8 ,big5 ,gb2312,gbk,gb18030等几种常用编码区别(转载)
原文出处:http://www.blogjava.net/xcp/archive/2009/10/29/coding2.html 最近老为编码问题而烦燥,下定决心一定要将其弄明白!本文主要总结网上一些 ...
随机推荐
- Nginx事件管理之概念描述
1. Nginx事件管理概述 首先,Nginx定义了一个核心模块ngx_events_module,这样在Nginx启动时会调用ngx_init_cycle方法解析配置项,一旦在 nginx.conf ...
- js小数点相乘或相除出现多位数的问题
最近做一个支付的项目需要做个计算器,所以发现了一个问题. 比如: 0.03/0.00003=999.9999999999999 0.0003*0.3=0.000029999999999999997 0 ...
- VisualVM通过ssl远程连接JVM
VisualVM通过密码连接JVM实例如下 https://www.cnblogs.com/qq931399960/p/10960573.html 虽然设置了密码,但还是不够安全,只要获取到密码,在任 ...
- 使用data_flow_ops构造batch数据集
1. tf.unstack(number, axis=0) 表示对数据进行拆分 import tensorflow as tf import numpy as np data = np.array( ...
- Cortex-M3 操作模式与特权等级
Cortex-M3支持2个模式(Handler模式.线程模式)和2个特权等级(特权级.非特权级). 当处理器处在线程模式时,既可以使用特权级,也可以使用非特权级. 当处理器处在Handler模式时,总 ...
- 什么是 AIDL 以及如何使用
①aidl 是 Android interface definition Language 的英文缩写,意思 Android 接口定义语言.②使用 aidl 可以帮助我们发布以及调用远程服务,实现跨进 ...
- 运维之思科篇——NAT基础配置
一. NAT(网络地址转换) 1. 作用:通过将内部网络的私有IP地址翻译成全球唯一的公网IP地址,使内部网络可以连接到互联网等外部网络上. 2. 优点: 节省公有合法IP地址 处理地址重叠 增强灵活 ...
- promise 实现红绿灯
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- Debian系统设置terminal快捷键
我安装的是debian gnome桌面版.安装完成之后,没有快捷键可以方便的打开terminal,需要自己设置这个快捷键 方法是: 桌面上点击右键==>设置==>键盘 ==>快捷键= ...
- postman插件的安装以及简单介绍
1:postman是干什么的? Postman官网上这么介绍的:“Modern software is built on APIs,Postman helps you develop APIs fas ...