本文我们简单聊聊汉字编码方案,例如 GB2312。
GB2312 的字符集
字符编码,是对字符进行的编码,那么首先得有一个字符集,然后再去编码,就像 ASCII 码也是对 ASCII 字符集进行的编码。
那中国的字符集怎么设定呢?以 GB2312 为例,国家标准局用了分区管理的方式,将公布的 6763 个两级汉字分为 94 个区,每个区 94 位,实际上就是把汉字表示成二维数组,每个汉字在数组中的下标就是区位码(表示其属于哪个区、哪个位)。区码和位码各是两位十进制数,因此一个汉字是 4 个十进制数,例如“中”字位于第 54 区 48 位,区位码位 5448
为什么使用分区
为什么要分区来管理呢?ASCII 编码方案多简单,不好吗?目前并未搜到为何这么设计,个人认为分区是为了方便管理。中国的汉字特别多,就好比学校中,由于学生太多,因此采用了分班管理的方式,每个班再给学生编号,这样比较好管理
感兴趣的同学,可以去国家标准网上查看 GB2312 的文档,国家标准 |GB/T 2312-1980,可以在线预览文档(没找到下载按钮,无法预览)
文档在线预览地址:在线预览 |GB/T 2312-1980, 部分内容:
区位码简单说明
我们继续来讲 GB2312 的区位码设计。在 94 个区中:
- 01 ~ 09 区:收录了除汉字外的 682 个字符
- 10 ~ 15 区:空白区,没有使用
- 16 ~ 55 区:收录了 3755 个一级汉字,按拼音排序
- 56 ~ 87 区:收录了 3008 个二级汉字,按部首/笔画排序,不太常用,生僻的一些汉字。
- 88 ~ 94 区:空白区
我们简单看看 01 ~ 09 区的字符:
第 16 ~ 55 区的截图如下。前面我们说过 “中”字位于第 54 区 48 位,区位码位 5448。读者也可以去看 在线预览 |GB/T 2312-1980 第 22 页:
56 ~ 87 区的部分截图如下:
GB2312 如何存储
我们之前只讲了区位码,但没有规定怎么在计算机里存储。我们以侃字为例,侃的区位码是 5709,我们将区和位分开,并转为 16 进制。57 对应 0x39, 09 对应的还是 0x09。然后将区码和位码分别加上 A0,得到 0xD9 和 0xA9,然后合并,就是 0xD90xA9:
为什么要加 A0:为了兼容 ASCII。GB2312 是双字节编码,为了与 ASCII 码区分开,字节的第 8 位必须是 1,所以至少要从 0x80(128, 1000 0000) 开始,但是根据上面的规定,0x80 - 0x9f 要留给控制块,所以只能从 0xA0 开始。那为什么 GB2312 编码不是从 0xA0 开始,而是 0xA1 开始呢? 因为 0xA0 正好是图形块的空格,所以就从 0xA1 编码,这就是 0xA0 的由来。
综上,一个汉字要占两个字节,两个字节均大于 127。
实践:查看汉字的 GB2312 码
如果你用过 Python,可以用以下代码打印出侃的 GB2312 码
print('侃'.encode('gb2312')) # 结果为'\xd9\xa9'
读者也可以新建一个 txt 文件,然后通过 IDE 或者编辑器的十六进制的方式查看文件,以 Sublime 为例:
这里不展开,有兴趣的读者请自行上网搜索。
如果你在 Linux 下,可以使用 hexdump 命令:
$hexdump 侃.txt
0000000 a9d9
GBK
因此,在 1995 年,中国发布了 GBK 编码,其包含了 GB2312 的所有内容,同时新增了近 20000 个新的汉字(繁体字)和符号
GBK 编码不再要求低字节要大于 127,只要第一个字节大于 127 就表示是一个汉字的开始。
标签:编码,预览,区位码,GB2312,汉字,如何,ASCII From: https://www.cnblogs.com/PeterJXL/p/18250286