文字与编码
复习
- 计算机的构成:计算机需要输入、输出、存储和处理功能;CPU 内的 ALU、控制器和寄存器共同处理指令和数据
- 计算机的数据表示:计算机用二进制表示数据,八进制和十六进制是二进制的简写
- 数据的大小与单位:认识了 bit、Byte 及更大的数据单位,以及了解了 1024 与 1000 的差异
TL;DR
- 计算机只能存 0 和 1,所以文字也要靠“编号”来表示
- 给每个字符分配一个数字编号,这套编号规则就叫 字符编码
- 英文字符不多,常用 ASCII 编码,全世界文字繁多而复杂,所以有一个统一编码 Unicode,中文编码常用方案是 UTF-8
- 同一个字符,在不同编码下可能占不同字节数
正文
前面两章讲的都是数字。可我们要在计算机上写文章、发消息,里面全是文字。计算机只认 0 和 1,文字怎么办?
答案很朴素:给每个字符编个号。
给字符编号
比如,我们约定 65 代表大写字母 A,66 代表 B,97 代表小写 a……把字符和数字一一对应起来,计算机只要存这些数字,就等于存下了文字。
这套“字符 → 数字”的约定,最早被标准化成 ASCII(American Standard Code for Information Interchange,美国信息交换标准代码)。它用 7 位二进制,能表示 128 个字符,够英文世界用了:
- 数字
0~9:编号 48~57 - 大写
A~Z:编号 65~90 - 小写
a~z:编号 97~122 - 常见的标点、空格、换行,也都各占一个号
所以,65 这个数字,到底是“数值 65”还是“字母 A”,取决于你怎么解读——后面讲有符号数时“同一串二进制既可能是正数也可能是负数”也是一样:编码只是一层人为约定。
英文不够用怎么办
ASCII 只有 128 个位置,英文够用,可中文有成千上万个汉字,日语、韩语、阿拉伯语也各有各的字符。128 个编号显然不够。
于是出现了更大的字符集 Unicode。它给全世界已知的文字都编了号,容量大到几十万,每个字符对应一个唯一编号(叫“码点”,例如汉字“中”的码点是 U+4E2D)。
Unicode 解决了“编号够不够”,“怎么存”也是个问题:如果每个字符都用很多位来存,英文文本就会浪费大量空间。
怎么存:UTF-8
为了解决存储问题,Unicode 有很多具体的实现方案,在中英文混合的情况下,最流行的是 UTF-8。它的聪明之处在于 变长:
- 英文字符只占 1 个字节,和 ASCII 完全兼容
- 常用汉字一般占 3 个字节
- 生僻字可能占 4 个字节
英文文本不浪费,中文也能存下。“一个汉字占 3 个字节”,说的就是 UTF-8。同一段文字,用不同编码保存,文件大小会不一样。一段纯英文文本,用 ASCII 编码,可能就比 UTF-8 小得多。
而这个时候,互联网上常见的“乱码”,也就能说的通了。比如经典的“烫烫烫”,“锟斤拷”之类。这是读的一方用错了约定。网上还有人专门总结了用 A 编码打开 B 编码的文件会出现什么样的乱码,可以搜一下,很有意思。
思考题
数字
65在内存里就是二进制0100 0001。如果一段数据里出现了0100 0001,你怎么知道它表示的是“数值 65”还是“字符 A”?
小结
知识点
- 文字也要靠“编号”变成二进制
- ASCII 与 128 个字符
- Unicode 与码点
- UTF-8 的变长存储
- 编码是人为约定
参考资料
- Wikipedia(zh):ASCII:ASCII 编码表
- Wikipedia(zh):Unicode:统一码
- Wikipedia(zh):UTF-8:变长编码方案
思考题答案(仅供参考)
没法只凭这串二进制判断,得看“上下文”。如果程序正按字符方式读取(比如一个字处理软件),它会把 0100 0001 当字符 A;如果按整数方式读取,它就是 65。这正是编码的核心:同一串比特,含义由读取时的约定决定。 这也提醒我们,程序里“数据类型”和“编码约定”必须前后一致,否则就会出现乱码或错误。
协议
本作品采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可。
封面图
设计师 | 南国微雪