zjffun blog

编码

更新于 写于

ASCII

8bit 进行表示,有 0xFF(256)种不同的状态

  • 0x00 ~ 0x20:控制码
  • 0x21 ~ 0x7F:空格、标点符号、数字、大小写字母
  • 0x80 ~ 0xFE:新的字母和符号

ASCII 编码表

国标(GB)编码 GB2312->GBK->GB18030

GB2312

GB2312 是对 ASCII 的中文扩展

  • 0x00 ~ 0x7F:原来的 ASCII
  • 0xA1A1 ~ 0xB0A1
  • 0xB0A1 ~ 0xF7FE:汉字
  • 0xF7FE ~ 0xFEFE

等中国人们得到计算机时,已经没有可以利用的字节状态来表示汉字,况且有 6000 多个常用汉字需要保存呢。于是国人就自主研发,把那些 127 号之后的奇异符号们直接取消掉。 规定:小于 127 的字符的意义与 ASCII 相同,但两个大于 127 的字符连在一起时,就表示一个汉字,前面的一个字节(他称之为高字节)从 0xA1 用到 0xF7,后面一个字节(低字节)从 0xA1 到 0xFE,这样我们就可以组合出大约 7000 多个简体汉字了。在这些编码里,我们还把数学符号、罗马希腊的字母、日文的假名们都编进去了,连在 ASCII 里本来就有的数字、标点、字母都统统重新编了两个字节长的编码,这就是常说的” 全角” 字符,而原来在 127 号以下的那些就叫” 半角” 字符了。

GB2312 编码表

GBK

GBK 是 GB2312 的拓展

中国的汉字太多了,后来还是不够用,于是干脆不再要求低字节一定是 127 号之后的内码,只要第一个字节是大于 127 就固定表示这是一个汉字的开始,不管后面跟的是不是扩展字符集里的内容。结果扩展之后的编码方案被称为 GBK,GBK 包括了 GB2312 的所有内容,同时又增加了近 20000 个新的汉字(包括繁体字)和符号。

GBK 编码表

GB18030

GB18030 是 GBK 的拓展

后来少数民族也要用电脑了,于是我们再扩展,又加了几千个新的少数民族的字,GBK 扩成了 GB18030。

Unicode

Unicode 只是对字符进行了编号,以字节的方式在计算机中存储这个编号的规则则是 UTF 或者 UCS 来定义的。

目前的 Unicode 字符分为 17 组编排,0x0000 至 0x10FFFF,每组称为平面(Plane),而每平面拥有 65536 个码位,共 1114112 个。

Unicode defines two mapping methods: the Unicode Transformation Format (UTF) encodings, and the Universal Coded Character Set (UCS) encodings.

UTF(UCS Transfer Format)标准

UTF8 就是每次 8 个位传输数据,而 UTF16 就是每次 16 个位,只不过为了传输时的可靠性,从 Unicode 到 UTF 时并不是直接的对应,而是要过一些算法和规则来转换。

Unicode 编码表

超简版:

html
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>
<div class="unicode">

</div>

<body>
    <script>
        let u_div = document.querySelector('.unicode'),
            u1 = Number.parseInt('007F', 16),
            u2 = Number.parseInt('07FF', 16),
            u3 = Number.parseInt('FFFF', 16),
            u4 = Number.parseInt('10FFFF', 16);

        for (let i = Number.parseInt('0000', 16); i < u1; i++) {
            u_div.append(document.createTextNode(String.fromCharCode(i)));
        }
        u_div.append(document.createElement('hr'));

        for (let i = Number.parseInt('0080', 16); i < u2; i++) {
            u_div.append(document.createTextNode(String.fromCharCode(i)));
        }
        u_div.append(document.createElement('hr'));

        for (let i = Number.parseInt('0800', 16); i < u3; i++) {
            u_div.append(document.createTextNode(String.fromCharCode(i)));
        }
        u_div.append(document.createElement('hr'));

        // 太多了。。
        // for (let i = Number.parseInt('10000', 16); i < u4; i++) {
        //     u_div.append(document.createTextNode(String.fromCharCode(i)));
        // }
    </script>
</body>

</html>

相互转换

Unicode 与国标(GB)编码

Unicode 在制订时没有考虑与任何一种现有的编码方案保持兼容,这使得 GBK 与 Unicode 在汉字的内码编排上完全是不一样的,没有一种简单的算术方法可以把文本内容从 Unicode 编码和另一种编码进行转换,这种转换必须通过查表来进行。

Unicode 与 UTF8

Unicode UTF-8
0000 - 007F 0xxxxxxx
0080 – 07FF 110xxxxx 10xxxxxx
0800 – FFFF 1110xxxx 10xxxxxx 10xxxxxx

UTF-8 中的每位 x 代表 Unicode 的一位二进制

参考:

  1. GB2312 不支持繁体,GBK 才支持。
  2. 某些汉字 Unicode 中有,GBK 中没有 T_T,如:“䗴” 字。