跳转至

文本编码

[[CON]] 我们了解到,原始数据可以被自由解释成任何形式,但我们总是希望软件彼此一致并兼容。它们应该以一种一致的方式保存和读取文本。

任何文本到数据转换的基本思想是在每个字符和原始比特序列之间建立双向映射。

[[STD]] 很久很久以前,存储空间是很昂贵的,软件在设计时也多半没有考虑到国际化的问题。所以,人们提出了相当有限的字母、数字、符号和控制字符的集合,并将其映射到较短的比特序列。在 ISO 拉丁文 1 中,一个字符需要 1 字节(8 比特)。在数学上,只有 256 个唯一的 8 比特序列,每一个序列都被定义成了某个特定的字符。 是 ISO Latin 1 包含的字符列表。其中的前 128 个和 ASCII 相同。

ASCII 和 ISO Latin 1 是文本编码标准,也就是人们通常说的编码

ASCII 只有不带有变音符号的拉丁字母,ISO Latin 1 则包含很少的变音拉丁字母(如 ü),这当然不能满足多种语言的需要。在过去的日子里,人们只能把他们的文本编辑器的编码切换到他们使用的语言的编码。在下表中,您可以看到相同的数据是如何被通过不同的编码,被映射成不同的文本的:

原始数据 使用 ISO 8859-1 Latin 1 读取 使用 ISO 8859-5 Latin / Cyrillic 读取
EF E9 ïé
(带有分音符的小写字母 i, 带有锐音符的小写字母 e)
ящ
(小写西里尔字母「ya」, 小写西里尔字母 「shcha」)

如果一段数据被编码过,则需要用这段数据的原始编码或与之兼容的编码打开。[[IMPL]] 通常,您的文本编辑器将根据文件内容猜测编码,但如果猜错了,你就会因为上述表格中体现的原因而看到错误的字符。您也可能看到矩形或问号,因为这些比特序列恰好在您打开的编码中未定义。

Unicode

[[STD]] 更晚些时候,有人为所有语言设计了被称作 Unicode 的单一标准。它的特定部分是 UTF-8UTF-16 等。Unicode 字符长度是可变的。这些名称中的数字代表每个字符的最小长度,其他字符的长度始终是这一最小单位的整数倍。Unicode 根据自己的规则将连续数据拆分为不同长度的段,然后将这些段映射到字符。Unicode 的设计者大致遵循如下规则:越常见的字符,其位序列越短。我们以这种方式节省了很多空间。

兼容性

[[STD]] 某些编码以特定方式和其他编码兼容。在 ASCII 中,一个字符需要 7 位。在 ISO Latin 1 中,一个字符需要 8 位,而前 128(0x000x7f)被定义为与 ASCII 相同,意思是说,如果 ASCII 数据被填充到 8 位并补足前导零,ISO Latin 1 与 ASCII 是单向兼容的。同样,UTF-8 也与 ISO Latin 1 兼容,因为 UTF-8 中的所有 8 位字符都被定义为与 ISO Latin 1 相同。

文本文件

大多数文本文件只是将每个字符的比特序列连接在一起,文件本身不能体现它自身的编码或它只是纯文本。这就是文本编辑器经常猜测文本文件使用的编码,而且通常(并不总是)正确的原因。如果您尝试了所有编码标准,但是仍然无法看到可读文本,那么您尝试打开的文件可能不是文本文件。

试一下

[[APPL]] 选择一个可以切换编码的文本编辑器。创建一个文件,将编辑器的编码模式设置为 ISO Latin 1,然后输入一些字符。将编辑器的模式切换到 Unicode,看看文本是否仍能正确显示。将西里尔文、希腊文、阿拉伯文或中文的一些字符粘贴到文件中,看看文本是否仍能正确显示。然后把编辑器的模式切换回 ISO Latin 1,看看这些新字符的显示情况。

你也可以时不时保存这个文件,并使用十六进制编辑器来查看它的原始状态。