应用程序如何知道字符编码?

时间:2018-11-28 14:17:35

标签: unicode encoding cat

可以说我有两个文件,如下所示:

$ 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))'
   £

我的逻辑有缺陷吗?我在这里想念什么?

2 个答案:

答案 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)

  

应用程序如何知道字符编码?

要么:

  1. (他们猜测-也许是启发式的。这不是“知道”。)
  2. 他们准确地告诉您要使用哪一个(通过文档,标准,约定等)。 (这也不是真正的“知道”。)
  3. 它们允许您告诉他们您正在使用哪个。

这是您的文件;你必须知道。