GB 2312

GB 2312 是 1980 年发布的中文编码,共收录 7445 个字符,有 6763 个汉字以及 682 个非汉字字符,其中一级汉字 3755 个,二级汉字 3008 个。

GB 2312 采用双字节编码,两字节最高位均为 1,所以可以兼容 ASCII 码。

整个字符集分为 94 个区,每个区有 94 个位,7445 个字符被填入到这 94*94 个区位中。
每个区位上只有一个字符,因此可用所在的区和位来对汉字进行编码,称为区位码。区位码加上 0x2020 就得到国标码。国标码再加上 0x8080 就得到了两字节的计算机内码。

1 和 94 对应的 16 进制分别为 0x01 和 0x5E。
所以区位码的范围是:0x0101~0x5E5E,加上 0x2020
得到国标码的范围是:0x2121~0x7E7E,加上 0x8080
得到内码的范围是:0xA1A1~0xFEFE

在 GB 2321 中:
1 到 9 区,为非汉字字符。
10 到 15 区,没有字符。
16 到 55 区,为一级汉字,按拼音排序。
56 到 87 区,为二级汉字,按部首/笔画排序。
88 到 94 区,没有字符。

所以对应到内码:
0xA1A1~0xA9FE 为非汉字字符。
0xAAA1~0xAFFE 无编码。
0xB0A1~0xF7FE 为汉字。
0xF8A1~0xFEFE 无编码。

GB 2312 编码表参考:
http://doc.chacuo.net/gb2312

GBK

GBK 即汉字内码扩展规范,共收录 21886 个汉字和非汉字字符。

兼容 GB 2312,同样采样双字节编码,同样兼容 ASCII 码,与 GB 2312 不同的是,它只要求第一个字节最高位为 1。 解码时,遇到首位为 1 的字节,就连同下一个字节一起表示一个 GBK 编码,遇到首位为 0 的字节,就直接按 ASCII 码处理。

GBK 编码范围为 0x8140~0xFEFE,第一个字节在 0x81~0xFE 之间,第二个字节在 0x40~0xFE 之间,剔除了第二个字节为 0x7F 的编码。

GBK 编码表参考:
http://doc.chacuo.net/gbk

GB 18030(较少用)

GB 18030 兼容 GBK 和 ASCII,共收录汉字 70244 个,采用一二四字节可变长编码。

Unicode

Unicode 是一个标准,定义了一个字符集以及这个字符集对应的一系列编码方案,即 Unicode 字符集和 UTF-8、UTF-16、UTF-32 等等编码。

通常我们说的 Unicode 仅仅指的是 Unicode 字符集,这个字符集的目的是收录全世界的所有字符,为每一个字符分配一个唯一的数字编号,这个数字编号用 Unicode 定义的术语来说就是 code point (译作码点或码位)。

Unicode 的码点记作 U+[XX]XXXX,X 表示16 进制数。码点的范围是 U+0000~U+10 FFFF。
类似于 GB 2312 按区划分字符集,Unicode 按平面(plane)划分字符集,将字符集划分为 17 个平面(plane 0 到 plane 16),每个平面包含 65536 个码点,码点范围是 U+0000~U+FFFF。其中,第一个平面,即 plane 0,又叫做 BMP(Basic Multilingual Plane,基本多语言平面),包含了世界上日常使用的绝大部分字符。

Unicode 字符集参考:
https://unicode-table.com/cn/

UTF-8、UTF-16、UTF-32

UTF 是 Unicode Transformation Format 的缩写,规定了 Unicode 码点转换为计算机内码的规则。

UTF-32 最简单粗暴,直接使用码点作为四字节内码。比较浪费空间,不是很常用。

考虑到平时使用的大多数字符都在 BMP(U+0000~U+FFFF)里,只需要使用两个字节编码即可。万一用到 BMP 以外的字符,再使用四个字节编码。这就是UTF-16。Java8 内部就是使用 UTF-16 编码字符串。

由于 UTF-16 和 UTF-32 都是一次读取 2 字节或 4字节,这样一是不兼容 ASCII 码,二是在有大小端之分的机器间传输时,需要考虑字节序的问题,否则会造成乱码。

UTF-8 不同于 UTF-16、UTF-32,能够兼容 ASCII 码,是一种变长字节的编码方式,每次读取一个字节,所以无需考虑字节序。

Unicode 标准提出使用 BOM(Byte Order Mark)来标识字节序。做法是在文件开头加上 “ZERO WIDTH NO-BREAK SPACE” 这个字符,这是一个零宽度不换行空格,是一个不可见字符,对应 Unicode 码点为 U+FEFF。
按理说 UTF-8 是不需要 BOM 的,但是为了在解码时明确区分 UTF-8 和其它编码,也可以加上 BOM,Unicode 标准也允许这么做。微软的很多软件就会默认在 UTF-8 编码的文件中加上 BOM,不过有时候,这种做法会造成很多不必要的麻烦。

下表是各种 UTF 的 BOM:

UTF 编码 BOM(十六进制)
UTF-8 without BOM
UTF-8 with BOM EF BB BF
UTF-16LE FF FE
UTF-16BE FE FF
UTF-32LE FF FE 00 00
UTF-32BE 00 00 FE FF

UTF-8 编码规则

UTF-8 使用 1 至 4 个字节为每个字符编码:

  • Unicode 码点在 U+0000~U+007F 之间的 ASCII 码字符,直接使用 1 字节编码;
  • Unicode 码点在 U+0080~U+07FF 之间的字符,包括带有变音符号的拉丁文、希腊文、西里尔字母、亚美尼亚语、希伯来文、阿拉伯文、叙利亚文等,使用 2 字节编码;
  • 其他语言的常用字符(包括中日韩文字、东南亚文字、中东文字等),使用 3 字节编码;
  • 其他极少使用的语言字符,使用 4 字节编码;

UTF-8 编码规则表:

Unicode 码点 bit 数 UTF-8(xxx 就是二进制的 Unicode 码点) byte 数
U+0000~U+007F 7 0xxx xxxx 1
U+0080~U+07FF 11 110x xxxx 10xx xxxx 2
U+0800~U+FFFF 16 1110 xxxx 10xx xxxx 10xx xxxx 3
U+1 0000~U+1F FFFF 21 1111 0xxx 10xx xxxx 10xx xxxx 10xx xxxx 4

以汉字“码”举例,说明 UTF-8 的编码过程:

Unicode 码点 U+7801
对应二进制 0111 1000 0000 0001
分为三部分 0111、1000 00、00 0001
UTF-8 模板 1110 xxxx 10xx xxxx 10xx xxxx
填充对应位置 1110 0111 1010 0000 1000 0001
编码结果 0xE7A081

UTF-16 编码规则

UTF-16 使用 2 或 4 个字节为每个字符编码:

  • Unicode 码点在 U+0000~U+FFFF 之间的字符,直接使用 2 字节编码。
  • Unicode 码点在 U+10000~U+10FFFF 之间的字符,使用 4 字节编码。具体来说就是:将码点减去 0x10000,然后把结果对应的二进制数分为两部分,高位部分用一个介于 0xD800~0xDBFF 之间的双字节存储,低位部分用一个介于 0xDC00~0xDFFF 之间的双字节存储。

UTF-16 编码规则表:

Unicode 码点范围 bit 数 UTF-16(二进制) byte 数
U+0000~U+FFFF 16 xxxx xxxx xxxx xxxx 2
U+1 0000~U+10 FFFF 20 1101 10xx xxxx xxxx 1101 11xx xxxx xxxx 4

2 字节编码直接使用码点没什么好说的,下面举个例子说明一下 4 字节编码:

Unicode码点 U+20000
减去0x10000 0x10000
对应二进制 0001 0000 0000 0000 0000
分成两部分 0001 0000 00、00 0000 0000
UTF-16 模板 1101 10xx xxxx xxxx 1101 11xx xxxx xxxx
填充对应位置 1101 1000 0100 0000 1101 1100 0000 0000
编码结果 0xD840DC00

位于 U+D800~U+DFFF 之间的 Unicode 码点是特别为四字节的 UTF-16 编码预留的,在这个范围内的码点没有指定任何字符。

记事本输入“联通”保存,再次打开时乱码的问题:

简单来讲就是,windows 自带的记事本,输入”联通“后,默认按照 ANSI 编码保存,ANSI 编码在中国指的就是 GBK 编码。而打开时,记事本发现文件也符合 UTF-8 的编码格式,便优先使用 UTF-8 解码,从而导致乱码。

具体的,“联通”的 GBK 编码为 0xC1AA 0xCDA8,都符合 UTF-8 的双字节编码格式(110x xxxx 10xx xxxx)。

参考:
https://baike.baidu.com/item/%E4%BF%A1%E6%81%AF%E4%BA%A4%E6%8D%A2%E7%94%A8%E6%B1%89%E5%AD%97%E7%BC%96%E7%A0%81%E5%AD%97%E7%AC%A6%E9%9B%86/8074272?fromtitle=GB2312&fromid=483170&fr=aladdin
https://baike.baidu.com/item/Unicode/750500?fr=aladdin#4_1
https://baike.baidu.com/item/UTF-8/481798?fr=aladdin
https://www.zhihu.com/question/23374078/answer/24385963
https://zhuanlan.zhihu.com/p/26261762?utm_source=qq&utm_medium=social&utm_oi=934366346112811008
https://blog.csdn.net/guxiaonuan/article/details/78678043#commentBox

字符编码(GB 2312、GBK、UTF-8、UTF-16)相关推荐

  1. Android字符编码转换,GBK转UTF-8

    Android字符编码转换,GBK转UTF-8 网上看了很多都不能用,最后看到这个方法,很靠谱,分享给大家! String str; str = new String(str.getBytes(&qu ...

  2. 深入理解-字符编码ASCII,GB2312,GBK,Unicode,UTF-8

    字符编码 简介 起初再考虑写不写这篇文章,感觉这篇文章比较枯燥乏味,而且自己感觉也没理解的太透彻,就把理解的记录下来,所以这是纪念版的 前方高能,非战斗人员请迅速撤离,我要开始装逼了. Go hard ...

  3. android utf-8 转 gbk编码,【字符编码系列】GBK,UTF-8,UTF-16之间的转换

    写在前面的话 本文属于 字符编码系列文章之一,更多请前往 字符编码系列. 大纲 不同编码转换的理论基础 UTF-16转UTF-8 UTF-16转GBK UTF-16和UTF-8之间的转换 UTF-16 ...

  4. 常见字符编码介绍以及相互转换

    最近在用JS时,涉及到了不同编码之间的转换.于是汇总了一些网上的资料,整合成了自己的文档.  -备忘录 知识点涉及: 字符编码基础,不同编码之间的转换,如UTF-8转UTF-16,如UTF-16转GB ...

  5. 编码标准-GB2312 GBK GB18030

    关于 ASCII编码 可以查看我的另外一篇博客 编码标准-ASCII 关于 Unicode 可以参考我的另外一篇博客 Unicode 编码标准-GB2312 GBK GB18030 基本概念 区位码 ...

  6. 关于字符集和字符编码自己汇总记录

    第零篇 第一篇 第二篇 第三篇 第四篇:关于"unicode字符是2个字节"这句话的讨论 关于Unicode的中文百科  https://zh.wikipedia.org/wiki ...

  7. 常用字符集及字符编码和Charset类

    计算机中储存的信息都是用二进制数表示的:而我们在屏幕上看到的英文.汉字等字符是二进制数转换之后的结果. 字符(Character) :是各种文字和符号的总称,包括各国家文字.标点符号.图形符号.数字等 ...

  8. Java字符编码知识简介

    1.基本信息 摘要:在Java应用程序特别是Web应用中,经常遇到字符的编码问题.为了防止出现乱码,首先需要了解字符编码的基本概念以及Java是如何处理字符编码的,这样就可以有目的地在输入/输出环节中 ...

  9. 小结字符集及字符编码问题

    原文转自我的个人博客--温馨咖啡小屋 字符编码问题一直深深困扰着我~无论是网页还是数据库抑或是单纯的文件字符流,总有各种奇怪的编码问题.之所以称之为奇怪其实主要还是因为我对于编码的知识了解太浅.近来深 ...

  10. 字符编码详解及利用C++ STL string遍历中文字符串

    作者:非妃是公主 专栏:<笔记><C++> 博客地址:https://blog.csdn.net/myf_666 个性签:顺境不惰,逆境不馁,以心制境,万事可成.--曾国藩 文 ...

最新文章

  1. 硬核!Python 四种变量的代码对象和反汇编分析
  2. 通过IIS操作修改服务器文件没有权限的解决办法
  3. 【目标检测】RCNN算法详解
  4. BlockingQueue常用方法add、off、put、take、poll使用说明
  5. int类型存小数 mysql_2020年最新版MySQL面试题(一)
  6. 吴恩达机器学习--单变量线性回归【学习笔记】
  7. 写python笔记本推荐_写个python程序帮你清理垃圾
  8. RabbitMQ 原文译03--发布和订阅
  9. No package ‘libmate-menu‘ found
  10. 计算机excel无法打开,双击Excel软件无法打开表格文件怎么办?
  11. uncode,utf8编码的文章
  12. 暴风影音下载|暴风影音播放器下载
  13. 什么叫死区时间_死区时间
  14. python 使用cv2、io.BytesIO处理图片二进制数据
  15. 极点五笔状态栏和候选窗口显隐
  16. 黑盒测试、灰盒测试、白盒测试、单元测试是什么?它们有什么区别?
  17. CSS文本样式和CSS3文本效果以及背景
  18. linux下的在线围棋程序--CGoban。(转)
  19. LINUX系统镜像下载总汇
  20. 一道数学题引发的惨案!4只小鸭子在一个圆形的大水池中,分别随机的出现圆圈中任意一点。4只鸭子在同一半圆内的概率是多少?

热门文章

  1. matlab prn文件,PRN格式文件 如何打开PRN文件 PRN是什么格式的文件 用什么打开 - The X 在线工具...
  2. imx226_【索尼IMX136LQJ-C、IMX236LQJ-C、IMX226CQJ-C、IMX274LQC-C、】价格_厂家 - 中国供应商...
  3. 微信小程序-基于云开发 CMS + Vant Weapp 电商 Demo 来了!
  4. <2021SC@SDUSC> 开源游戏引擎 Overload 代码模块分析 之 OvTools(七)—— 终篇总结
  5. java飞机大战开始游戏按钮素材_飞机大战图片素材(全)
  6. 谈谈你怎么理解产品经理
  7. 爬取淘宝评论以及词云图
  8. 基于Ubuntu的linux环境制作嵌入式SD/TF启动卡
  9. matlab 试验设计,试验设计与MATLAB数据分析
  10. 使用ToStringBuilder.reflectionToString重写toString方法