理清计算机汉字编码问题(上)

1. 常见编码

1.1 ASCII

  ASCII(American Standard Code for Information Interchange:美国信息交换标准代码)是基于拉丁字母的一套电脑编码系统,主要用于显示现代英语和其他西欧语言。它是现今最通用的信息交换标准,并等同于国际标准ISO/IEC 646。
  ASCII码表分为两部分:控制字符和可显示字符。这个不用多解释,相信学过C语言或者计算机电子信息相关专业的都涉及,更多请参考ASCII码对照表

1.2 汉字机内码

  汉字机内码,又称“汉字ASCII码”,简称“内码”,指计算机内部存储,处理加工和传输汉字时所用的由0和1符号组成的代码。输入码被接受后就由汉字操作系统的“输入码转换模块”转换为机内码,与所采用的键盘输入法无关。机内码是汉字最基本的编码,不管是什么汉字系统和汉字输入方法,输入的汉字外码到机器内部都要转换成机内码,才能被存储和进行各种处理。
关于国标码、区位码和机内码之间的换算,参考

  1. CSDN ~ https://blog.csdn.net/sxhelijian/article/details/24498045
  2. 博客园 ~ https://www.cnblogs.com/hrhguanli/p/3805799.html

C语言获取汉字机内码、区位码、国际码:

#include<stdio.h>
void main(void) {
	unsigned char temp[2];
	scanf("%s",temp);
	printf("机内码高字节是0x%.2x\n",temp[0]);
	printf("机内码低字节是0x%.2x\n",temp[1]);
	printf("区位码区码是%2d\n",temp[0]-0xa0);
	printf("区位码位码是%2d\n",temp[1]-0xa0);
	printf("国际码高字节是0x%.2x\n",temp[0]-0x80);
	printf("国际码低字节是0x%.2x\n",temp[1]-0x80);
}

1.3 Unicode

  Unicode(统一码、万国码、单一码)是计算机科学领域里的一项业界标准,包括字符集、编码方案等。Unicode 是为了解决传统的字符编码方案的局限而产生的,它为每种语言中的每个字符设定了统一并且唯一的二进制编码,以满足跨语言、跨平台进行文本转换、处理的要求。1990年开始研发,1994年正式公布。
  Unicode只有一个字符集,中、日、韩的三种文字占用了Unicode中0x3000到0x9FFF的部分 Unicode目前普遍采用的是UCS-2,它用两个字节来编码一个字符, 比如汉字"经"的编码是0x7ECF,注意字符码一般用十六进制来 表示,为了与十进制区分,十六进制以0x开头,0x7ECF转换成十进制 就是32463,UCS-2用两个字节来编码字符,两个字节就是16位二进制, 2的16次方等于65536,所以UCS-2最多能编码65536个字符。 编码从0到127的字符与ASCII编码的字符一样,比如字母"a"的Unicode 编码是0x0061,十进制是97,而"a"的ASCII编码是0x61,十进制也是97, 对于汉字的编码,事实上Unicode对汉字支持不怎么好,这也是没办法的, 简体和繁体总共有六七万个汉字,而UCS-2最多能表示65536个,才六万 多个,所以Unicode只能排除一些几乎不用的汉字,好在常用的简体汉字 也不过七千多个,为了能表示所有汉字,Unicode也有UCS-4规范,就是用 4个字节来编码字符。
更多请参考 ~ Unicode字符表

1.4 UTF-8

  互联网的普及,强烈要求出现一种统一的编码方式。UTF-8 就是在互联网上使用最广的一种 Unicode 的实现方式。其他实现方式还包括 UTF-16(字符用两个字节或四个字节表示)和 UTF-32(字符用四个字节表示),不过在互联网上基本不用。重复一遍,这里的关系是,UTF-8 是 Unicode 的实现方式之一
  UTF-8 最大的一个特点,就是它是一种变长的编码方式。它可以使用1~4个字节表示一个符号,根据不同的符号而变化字节长度。

UTF-8 的编码规则很简单,只有二条:

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

下表总结了编码规则,字母x表示可用编码的位。

Unicode符号范围(十六进制) UTF-8编码方式(二进制)
0000 0000-0000 007F 0xxxxxxx
0000 0080-0000 07FF 110xxxxx 10xxxxxx
0000 0800-0000 FFFF 1110xxxx 10xxxxxx 10xxxxxx
0001 0000-0010 FFFF 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx

  跟据上表,解读 UTF-8 编码非常简单。如果一个字节的第一位是0,则这个字节单独就是一个字符;如果第一位是1,则连续有多少个1,就表示当前字符占用多少个字节。
下面,还是以汉字严为例,演示如何实现 UTF-8 编码:
  严的 Unicode 是4E25(100111000100101),根据上表,可以发现4E25处在第三行的范围内(0000 0800 - 0000 FFFF),因此严的 UTF-8 编码需要三个字节,即格式是1110xxxx 10xxxxxx 10xxxxxx。然后,从严的最后一个二进制位开始,依次从后向前填入格式中的x,多出的位补0。这样就得到了,严的 UTF-8 编码是11100100 10111000 10100101,转换成十六进制就是E4B8A5。

1.5 GBK、GB2312

  GBK汉字国标扩展码,基本上采用了原来GB2312-80所有的汉字及码位,并涵盖了原Unicode中所有的汉字20902。GBK编码是中国大陆制订的、等同于UCS的新的中文编码扩展国家标准。
  GB 2312或GB 2312-80是一个简体中文字符集的中国国家标准,GB 2312标准共收录6763个汉字。

1.6 GBK/GB2312、UTF-8、Unicode区别和联系

想要进一步弄清楚,GBK/GB2312、UTF-8和Unicode间的区别与联系,请仔细阅读下面这6篇不错的文章。

  1. 字符编码笔记:ASCII,Unicode 和 UTF-8
  2. ASCII,Unicode和UTF-8终于找到一个能完全搞清楚的文章了
  3. UTF-8 GBK UTF8 GB2312之间的区别和关系
  4. 编码之------Unicode到底是什么?神马utf-8和gbk到底是什么?utf-8和Unicode关系?
  5. 字符编码GB2312、GBK、UTF-8的区别
  6. 区分: 编码方式 字符集 Unicode UTF-8

2. OS中通用的字符编码工作方式

工作方式

  1. 在计算机内存中,统一使用Unicode编码,当需要保存到硬盘或者需要传输的时候,就转换为UTF-8编码;
  2. 用记事本编辑的时候,从文件读取的UTF-8字符被转换为Unicode字符到内存里,编辑完成后,保存的时候再把Unicode转换为UTF-8保存到文件;
  3. 浏览网页的时候,服务器会把动态生成的Unicode内容转换为UTF-8再传输到浏览器。

3. 总结

计算机中文编码
  在操作系统(Windows、安卓)中,字符编码工作方式参照上文【字符编码工作方式】。但在MCU微机中,处理方式不一样,在微机中由于资源有限,通常是通过汉字机内码计算汉字字符对应的地址,然后查询字库IC(带rom或者flash)显示。上图中,汉字在计算机内存储、处理/传输都是机内码,但为了信息交换于是便产生了国标(GBK/GB2312)即《信息交换用汉字编码字符集》,国标当然只适用于国内,于是国际上便产生了Unicode万国码,它又仅仅定义了一个字符集,UTF-8则就是按照Unicode字符实现的一种编码
  刚开始就很想弄懂Unicode、GBK/GB2312、UTF-8和机内码,彻底分清它们,但是查询了之后很多概念容易一头雾水。透过上图,大家应该很容易,理清它们间的关系和区别,相信在开发中遇到汉字编码都会迎刃而解,嘻嘻!
附:

  1. UTF-8转Unicode ~ http://tool.oschina.net/encode?type=2
  2. 汉字字符集编码查询 ~ https://www.qqxiuzi.cn/bianma/zifuji.php
  3. 16进制到文本字符串的转换,在线实时转换 ~ http://www.bejson.com/convert/ox2str/
发布了99 篇原创文章 · 获赞 185 · 访问量 20万+

猜你喜欢

转载自blog.csdn.net/Bluechalk/article/details/89175920