区分同一文件中的ascii和UTF-8字符

区分同一文件中的ascii和UTF-8字符

在 Ubuntu 18.04 上,我创建了一个仅包含一个 UTF-8 字符的虚拟文本文件è.其他角色全部是ascii

$ cat dummytext
Hello
Helloè

这是结果hexdump

$ hexdump -C dummyfile
00000000  48 65 6c 6c 6f 0a 48 65  6c 6c 6f c3 a8 0a        |Hello.Hello...|
0000000e

该文件被标识为

$ file dummyfile
dummyfile2: UTF-8 Unicode text

每个字符都由一个表示单身的字节,除了UTF-8è字符,即c3a8,所以用2个字节表示。如果用于表示每个字符的字节数不是恒定的,如何正确解释文件内容?

我的猜测:也许解析器在遇到大于最后一个ascii字符的十六进制值时7F(这是 的情况c3),被迫读取至少另一个字节,以确定要打印的正确字符?

答案1

BSD 手册第 5 节中有关 UTF8 的页面内容如下:

描述

UTF-8 编码将 UCS-4 字符表示为八位位组序列,每个字符使用 1 到 6 之间的数字。它向后兼容 ASCII,因此0x00-0x7f请参阅 ASCII 字符集。

非 ASCII 字符的多字节编码完全由设置了高位的字节组成。实际的编码如下表所示:

 [0x00000000 - 0x0000007f] [00000000.0bbbbbbb] -> 0bbbbbbb
 [0x00000080 - 0x000007ff] [00000bbb.bbbbbbbb] -> 110bbbbb, 10bbbbbb
 [0x00000800 - 0x0000ffff] [bbbbbbbb.bbbbbbbb] ->
         1110bbbb, 10bbbbbb, 10bbbbbb
 [0x00010000 - 0x001fffff] [00000000.000bbbbb.bbbbbbbb.bbbbbbbb] ->
         11110bbb, 10bbbbbb, 10bbbbbb, 10bbbbbb
 [0x00200000 - 0x03ffffff] [000000bb.bbbbbbbb.bbbbbbbb.bbbbbbbb] ->
         111110bb, 10bbbbbb, 10bbbbbb, 10bbbbbb, 10bbbbbb
 [0x04000000 - 0x7fffffff] [0bbbbbbb.bbbbbbbb.bbbbbbbb.bbbbbbbb] ->
         1111110b, 10bbbbbb, 10bbbbbb, 10bbbbbb, 10bbbbbb, 10bbbbbb

如果存在多个值的表示形式(例如,0x00; 0xC0 0x80; 0xE0 0x80 0x80),则始终使用最短的表示形式。较长的字符会被检测为错误,因为它们会带来潜在的安全风险,并会破坏 1:1 字符:八位字节序列映射。

Linux 手册第 7 节中有关 UTF8 的页面类似地写道:

描述

[... UTF-8 在某些情况下比 UCS-2 更好,部分原因是,大多数 UNIX 工具都需要 ASCII 文件,并且在没有重大修改的情况下无法将 16 位字读取为字符。 [...]

Unicode 和 UCS 的 UTF-8 编码不存在这些问题,并且是 UNIX 风格的操作系统上使用 Unicode 的常用方式。

特性

UTF-8 编码具有以下优良特性:

  • UCS 字符0x000000000x0000007f经典的 US-ASCII 字符)简单地编码为字节0x000x7fASCII 兼容性)。这意味着仅包含 7 位 ASCII 字符的文件和字符串在 ASCII 和 UTF-8 下具有相同的编码。

所以实际上不可能区分 ASCII 和 UTF-8,因为在 UTF-8 文件中,ASCIIUTF-8。 file查看文件的前 96KiB 并尝试确定它是什么。由于它看到多个 UTF-8 代码序列,因此它确定该文件为 UTF-8,因为它是 ASCII 的严格超集。

相关内容