【8.24】计算机基础 - 必须了解的 Unicode 和 字符集

418 阅读5分钟

这是我参与8月更文挑战的第22天,活动详情查看:8月更文挑战

计算机存储回顾

在前面的文章,计算机存储基础中,我们了解到,计算机最小的存储单元是位,位仅储存 0 或 1

1字节 = 8位,那么每一位有 0 或 1 两种选择,8位就是 2^8(2的8次方),256种组合方式,于是8位可以表示 0-255 这个范围的数字,比如 00010000 是 32

ASCII

上个世纪60年代,美国制定了一套字符编码,制定英语字符和二进制之间的关系,这就是 ASCII 码,一直沿用至今

ASCII 码一共规定了 128 个字符的编码,从 0(00000000)-127(01111111),其中比如 space 空格是 32,A 是 65,下图是所有的可显示字符,小于 32 和 127 的字符属于控制字符

image.png

我们可以看到,这 128 个字符,只占了一个字节的后面 7 位,最前面的一位始终为 0

非 ASCII

如果只是使用这 128 个字符,可以满足英文的存储,但是不同国家有各自的语言,大家同时想要把各自的语言对应的字符,放到目前空闲的 128-155 位置上,各自国家有各自的编码方式。

比如,130在法语编码中代表了é,在希伯来语编码中却代表了字母Gimel (ג),在俄语中又代表了其他字符,这样就导致,在同一个计算机上想要显示两种语言是不可能的,因为他们的编码方式不同。这个问题在亚洲国家就更严重了,汉字就多达10万左右。

如果我们只使用英语,或者从未把字符串从一台计算机移动到另一台,那它始终是可以工作的,但是一旦互联网出现,把字符串从一台计算机移动到另一台,那么他们表示的含义就会不同,整个混乱的局面就将无法收拾,幸运的是 unicode 被发明了~

Unicode

Unicode 是一个符号集合,将世界上所有的符号都纳入其中,每个符号有一个唯一的编码

Unicode 当然是一个很大的集合,现在的规模可以容纳100多万个符号。每个符号的编码都不一样,比如,U+0639表示阿拉伯字母AinU+0041表示英语的大写字母AU+4E25表示汉字。具体的符号对应表,可以查询unicode.org,或者专门的汉字对应表

但是 Unicode 只是一个符号集合,规定了比如 对应的代码为 U+4E25,其中 U + 代表 Unicode 代码,4E25 代表它的 16 进制代码,转换成二进制有 15 位(100111000100101),那么我们应该在计算机上如何存储呢?这样就会产生两个问题:

  1. 如何把 Unicode 和 ASCII 码区分,如何知道是几个字节表示一个字符?
  2. 如果统一用 3、4 个字节表示一个字符,那么对于 ASCII,前面的几位将全部是 0,对于空间是一个很大的浪费

UTF-8

UTF-8 是 Unicode 的一种实现方式。它解决了前面提到的两个问题。其他实现方式还包括 UTF-16(字符用两个字节或四个字节表示)和 UTF-32(字符用四个字节表示),不过在互联网上基本不用。

UTF-8 最大的一个特点,就是它是一种变长的编码方式。它可以使用1-4个字节表示一个符号,根据不同的符号而变化字节长度。

它的编码规则很简单,只有两条: 1)对于单字节的字符,第一位始终为 0,后面 7 位是这个字符的 Unicode 码,这样对于英语字母来说,UTF-8 和 ASCII 码始终相同 2)对于 n 字节的字符(n>1),第一个字节的前 n 位都设置成1,第 n+1 位设为 0,后面的字节前两位都设置成 10,对于没有提到的二进制位,填充为这个字符的 Unicode 码

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

比如前面说的,对应的代码为 4E25(100111000100101),对应上表的第三行,于是它的编码格式为 1110xxxx 10xxxxxx 10xxxxxx,从最后它的一个二进制位开始,依次从后往前填充,多出的位补 0,于是,填充完它的 Unicode 码后为 11100100 10111000 10100101

最后

总结一下我们平时开发需要注意 在不知道字符串使用什么编码的情况下,拥有字符串是没有意义的,因此,要想打开一个文本文件,就必须知道它的编码方式,否则用错误的编码方式解读,就会出现乱码。为什么电子邮件常常出现乱码?就是因为发信人和收信人使用的编码方式不一样。

本文参考:

阮一峰老师的博客:www.ruanyifeng.com/blog/2007/1…

每个软件开发人员绝对必须了解Unicode和字符集:www.joelonsoftware.com/2003/10/08/…