ASCII、GB2312、Unicode和UTF-8

2024-09-02 03:36
文章标签 ascii utf unicode gb2312

本文主要是介绍ASCII、GB2312、Unicode和UTF-8,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

ASCII

我们知道,计算机内部,所有信息最终都是一个二进制值。每一个二进制位(bit)有01两种状态,因此八个二进制位就可以组合出256种状态,这被称为一个字节(byte)。也就是说,一个字节一共可以用来表示256种不同的状态,每一个状态对应一个符号,就是256个符号,从0000000011111111

上个世纪60年代,美国制定了一套字符编码,对英语字符与二进制位之间的关系,做了统一规定。这被称为 ASCII 码(全称是“美国信息交换标准码”,American Standard Code for Information Interchange),一直沿用至今。

ASCII 码一共规定了128个字符的编码,比如空格SPACE是32(二进制00100000),大写的字母A是65(二进制01000001)。这128个符号(包括32个不能打印出来的控制符号),只占用了一个字节的后面7位,最前面的一位统一规定为0

但这仅适用于英文字母、数字和一部分符号,世界上还有许多语言的字符需要能够被计算机系统处理,这样就需要一个比ASCII大得多的字符集囊括这些字符。

Unicode 就是用来解决这些问题的。

GB2312

GB2312 编码,就是在 ASCII 编码的基础上进行扩充的,它规定如下:

ASCII 的字符完整地包含在GB2312里,编码不变,仍然是以0开头,用一个字节来表示一个字符;对于ASCII没有的字符,就用1开头来区分,用两个字节合起来表示一个字符。

这样,在解码的时候,遇到字节是以0开头的,就知道这一个字节就表示了一个字符;遇到字节是以1开头的,就知道要加上下一个字节合起来表示一个字符。这样就在 GB2312 中既把ASCII的字符包含了进来,又能将它们区分出来,能达到兼容的效果了

GBK 即汉字内码扩展规范,其中 K 为汉语拼音扩展中扩字的声母。共收入 21886 个汉字和图形符号。

Unicode

这是全世界最大的字符集,相对于ASCII码,Unicode大大扩展了编码位数到16 - 32位,意味着它理论上最多可以容纳 2 32 ≈ 42 亿 2^{32}≈42亿 23242亿 个字符。Unicode包含了各种字母、中日韩文字、emoji等几乎所有语言和领域的符号,如汉字“我”对应的Unicode是01100010 00010001,写成16进制就是6211。现在互联网上传递、展示所使用的编码基本都是Unicode。它的最低7位与ASCII码是完全兼容的,即如果用16位Unicode来表示大写字母A,就会写成00000000 01000001。

Unicode 的问题

需要注意的是,Unicode 只是一个符号集,它只规定了符号的二进制代码,却没有规定这个二进制代码应该如何存储。
有两个严重的问题:

  1. 怎么才能知道一个字节表示一个符号,而不是三个字节表示
  2. 如果统一用三个字节表示一个符号,那么英文字符必然存在浪费

UTF-8

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 码。

下表总结了编码规则

Unicode符号范围UTF-8编码方式
(十六进制)(二进制)
0000 0000-0000 007F0xxxxxxx
0000 0080-0000 07FF110xxxxx 10xxxxxx
0000 0800-0000 FFFF1110xxxx 10xxxxxx 10xxxxxx
0001 0000-0010 FFFF11110xxx 10xxxxxx 10xxxxxx 10xxxxxx

总结

  1. ANSI:文件的编码就是两个字节D1 CF,这正是的 GB2312 编码,这也暗示 GB2312 是采用大头方式存储的。
  2. Unicode:编码是四个字节FF FE 25 4E,其中FF FE表明是小头方式存储,真正的编码是4E 25
  3. Unicode big endian:编码是四个字节FE FF 4E 25,其中FE FF表明是大头方式存储。
  4. UTF-8:编码是六个字节EF BB BF E4 B8 A5,前三个字节EF BB BF表示这是UTF-8编码,后三个E4B8A5就是的具体编码,它的存储顺序与编码顺序是一致的。

**简单来说:**Unicode、GBK和Big5码等就是编码的值(也就是术语“字符集”),而UTF-8、UTF-16、UTF32之类就是这个值的表现形式(即术语“编码格式”)。

**另外:**Unicode、GBK和Big5码等字符集是不兼容的,同一个汉字在这三个字符集里的码值是完全不一样的。如"汉"的Unicode值与gbk就是不一样的,假设Unicode为a040,GBK为b030。以UTF-8为例,UTF-8码完全只针对Unicode来组织的,如果GBK要转UTF-8必须先转Unicode码,再转UTF-8就OK了。

即GBK、GB2312等与UTF8之间都必须通过Unicode编码才能相互转换:

  1. GBK、GB2312 --先转–> Unicode --再转–> UTF8
  2. UTF8 --先转–> Unicode --再转–> GBK、GB2312

参考文章

  1. 字符编码那点事:快速理解ASCII、Unicode、GBK和UTF-8 - 知乎 (zhihu.com)
  2. ASCII、Unicode、UTF-8、GBK的区别与联系_ascii unicode utf-8 gbk区别-CSDN博客
  3. 字符编码笔记:ASCII,Unicode 和 UTF-8 - 阮一峰的网络日志 (ruanyifeng.com)
  4. 【编码】彻底弄懂ASCII、Unicode、UTF-8之间的关系 - 大唐西域都护 - 博客园 (cnblogs.com)
  5. 一文看懂字符编码 - Unicode、UTF8、GBK、GB2312、ANSI和ASCII - 兔子先生wt - 博客园 (cnblogs.com)

这篇关于ASCII、GB2312、Unicode和UTF-8的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1128880

相关文章

C++ | Leetcode C++题解之第393题UTF-8编码验证

题目: 题解: class Solution {public:static const int MASK1 = 1 << 7;static const int MASK2 = (1 << 7) + (1 << 6);bool isValid(int num) {return (num & MASK2) == MASK1;}int getBytes(int num) {if ((num &

C语言 | Leetcode C语言题解之第393题UTF-8编码验证

题目: 题解: static const int MASK1 = 1 << 7;static const int MASK2 = (1 << 7) + (1 << 6);bool isValid(int num) {return (num & MASK2) == MASK1;}int getBytes(int num) {if ((num & MASK1) == 0) {return

在Unity环境中使用UTF-8编码

为什么要讨论这个问题         为了避免乱码和更好的跨平台         我刚开始开发时是使用VS开发,Unity自身默认使用UTF-8 without BOM格式,但是在Unity中创建一个脚本,使用VS打开,VS自身默认使用GB2312(它应该是对应了你电脑的window版本默认选取了国标编码,或者是因为一些其他的原因)读取脚本,默认是看不到在VS中的编码格式,下面我介绍一种简单快

批量文件编码转换用python实现的utf8转gb2312,vscode设置特殊文件的默认打开编码

批量文件编码转换用python实现的utf8转gb2312, 任意编码之间的相互转换都是可以的.改一下下面的参数即可 convert.py文件内容如下 import osimport globimport chardet#检测文件编码类型def detect_file_encoding(file_path):with open(file_path, 'rb') as f:data = f

【python 编码问题】UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-4: ordinal not

插入oracle 数据发生 错误:UnicodeEncodeError: 'ascii' codec can't encode characters in position 131-136: ordinal not in range(128) 先说解决办法: python2.7版本,在开头加入下面语句 import sysreload(sys)sys.setdefaultencoding

1字节的UTF-8序列的字节1无效

使用DOMReader解析XML文档时候报错”1字节的UTF-8序列的字节1无效”,我这里的解决方法。 1.手动将< ? xml version=”1.0” encoding=”UTF-8”?>中的UTF-8更改成UTF8,这样就可以了。 2.使用文本编译器把xml文档改成以UTF8无BOM编码格式就可以了。

页面jsp编码utf-8,传递中文参数到java后台出现乱码

1、前台页面jsp的编码是contentType=”text/html; charset=utf-8” 后台编码是gdk,传递中文参数时出现乱码,后台接收到传递的参数时需要进行转换才能解决乱码问题。 new String(this.getParameter("teacherName").getBytes("iso-8859-1"),"utf-8") 2、google浏览器显示正常,但是IE浏

(转)mysql按字段排序 按照字段的数值大小排序,而非 ascii码排序

参考:http://www.cnblogs.com/codefly-sun/p/5898738.html     如果是varchar类型, 排序后是这样的: 就是对mysql数值字符串类型进行排序,在默认情况下使用order by 字段名称 desc/asc 进行排序的时候,mysql进行的排序规则是按照ASCII码进行排序的,并不会自动的识别出这些数据是数值   ,百度了一下,

Android 打开 GBK项目如何设置成UTF-8

1.标题 今天打开一个eclipse老项目,编码格式为GBK,Android studio导入项目报错,本人想到一个方案就是批量修改文件格式从 GBK到 UTF-8,这样可以一键解决问题 2.开发脚本 使用前请备份代码   使用前请备份代码   使用前请备份代码 脚本代码如下,保存到文件下为 shell.ps1 # 获取当前脚本的所在目录$folderPath = Get-Loca

Golang | Leetcode Golang题解之第393题UTF-8编码验证

题目: 题解: const mask1, mask2 = 1 << 7, 1<<7 | 1<<6func getBytes(num int) int {if num&mask1 == 0 {return 1}n := 0for mask := mask1; num&mask != 0; mask >>= 1 {n++if n > 4 {return -1}}if n >= 2 {retur