在同一文件中區分 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
)時,被迫讀取至少另一個字節,以確定要列印的正確字元?
在 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 is situationally better than UCS-2 in part because i $$此外,大多數 UNIX 工具都需要 ASCII 文件,如果不進行重大修改,就無法將 16 位字作為字元讀取。$$ … $$ Unicode 和 UCS 的 UTF-8 編碼不存在這些問題,是 Unicode 在 UNIX 風格的作業系統上使用的常用方式。
特性
UTF-8 編碼具有以下優點:
- UCS 字元
0x00000000
to0x0000007f
(經典的 US-ASCII 字元)被簡單地編碼為字節0x00
to0x7f
(ASCII 兼容性)。這意味著僅包含 7 位 ASCII 字元的文件和字元串在 ASCII 和 UTF-8 下具有相同的編碼。所以實際上不可能區分 ASCII 和 UTF-8,因為在 UTF-8 文件中,ASCII是UTF-8。
file
查看文件的前 96KiB 並嘗試確定它是什麼。因為它看到多個 UTF-8 程式碼序列,所以它確定文件為 UTF-8,因為它是 ASCII 的嚴格超集。