可以说我有两个文件,如下所示:
$ ll
total 8
-rw-rw-r--. 1 matias matias 6 Nov 27 20:25 ascii.txt
-rw-rw-r--. 1 matias matias 8 Nov 28 21:57 unicode.txt
两者都包含一行文本,但是第二个文件中有一个额外的字符,如下所示(希腊字母Sigma):
$ cat ascii.txt
matias
$ cat unicode.txt
matiasΣ
如果我通过 file 命令传递它们,则为输出:
$ file *
ascii.txt: ASCII text, with no line terminators
unicode.txt: UTF-8 Unicode text, with no line terminators
似乎还可以。现在,如果我对文件进行 hexdump ,我会得到:
$ hexdump -C ascii.txt
00000000 6d 61 74 69 61 73 |matias|
00000006
$ hexdump -C unicode.txt
00000000 6d 61 74 69 61 73 ce a3 |matias..|
00000008
所以,我的问题是,作为 cat 的应用程序如何知道最后两个字节实际上是单个Unicode字符。如果我单独打印最后两个字节,我将得到:
$ printf '%d' '0xce'
206
$ printf '%d' '0xa3'
163
使用扩展ASCII的是:
$ py3 -c 'print(chr(206))'
Î
$ py3 -c 'print(chr(163))'
£
我的逻辑有缺陷吗?我在这里想念什么?
答案 0 :(得分:1)
命令行工具使用字节-它们接收字节并发送字节。
字符的概念(由一个或多个字节表示)是对原始字节的特定于任务的解释。
当您在UTF-8文件上调用cat
时,我认为它只是转发读取的字节而无需关心字符。
但是您的终端必须显示cat
的输出,请 注意将字节解释为字符,并为字节序列206、163显示单个字符。
通过其配置(locale
环境变量等),您的终端显然假定文本IO发生在UTF-8中。
如果违反了此假设(例如,如果命令隔离发送字节206,这是无效的UTF-8),您将看到符号或其他文本垃圾。
由于UTF-8设计为与ASCII向后兼容,因此可以将ASCII文本文件视为UTF-8文件(是 UTF-8)。
尽管cat
可能并不在乎字符,但其他许多命令也是如此,例如。 wc -m
命令来计算文本文件中的字符(不是字节!)。
这些命令都需要知道UTF-8(或您的终端编码是什么)如何将字节映射为字符,反之亦然。
例如,当您使用Python print(chr(206))
时,它会将字节195、142发送到STDOUT,因为:
(a)已经确定您的终端期望使用UTF-8,并且(b)字符“α”(Unicode代码点206所对应的字符)在UTF-8中用这两个字节表示。
最后,终端显示“Δ,因为它将两个字节解码为相应的字符。
答案 1 :(得分:0)
应用程序如何知道字符编码?
要么:
这是您的文件;你必须知道。