ASCII。ASCII 在表示英文字符方面做得非常好,因为它是美国信息交换标准代码(American Standard Code for Information Interchange)。
对于英语以外的语言,情况就变得更复杂了。在计算机发展的早期,存在许多相互竞争的非英语字符编码标准,要正确解释一个字符串,你需要同时知道它的取值和编码。例如,两种常见的编码是 Latin1(又称 ISO-8859-1,用于西欧语言)和 Latin2(又称 ISO-8859-2,用于东欧语言)。在 Latin1 中,字节 b1 是 "±",但在 Latin2 中,它是 "ą"!幸运的是,如今有一个几乎在所有地方都得到支持的标准:UTF-8。UTF-8 几乎可以编码当今人类使用的每一个字符,以及许多额外的符号(比如 emoji!表情符号)。
readr 在所有地方都使用 UTF-8:它在读取数据时假定数据是 UTF-8 编码的,并且在写出时也总是使用 UTF-8。这是一个很好的默认设置,但对于由不理解 UTF-8 的较旧系统产生的数据会失败。如果你遇到了这种情况,打印字符串时它们会看起来很奇怪。有时只有一两个字符会乱掉;其他时候你会得到完全的乱码。例如:
x1 <- "El Ni\xf1o was particularly bad this year" x2 <- "\x82\xb1\x82\xf1\x82\xc9\x82\xbf\x82\xcd"
要解决这个问题,你需要在 parse_character() 中指定编码:
parse_character(x1, locale = locale(encoding = "Latin1")) #> [1] "El Niño was particularly bad this year" parse_character(x2, locale = locale(encoding = "Shift-JIS")) #> [1] "こんにちは"
如何找到正确的编码呢?如果幸运的话,它会包含在数据文档的某处。不幸的是,情况很少如此,因此 readr 提供了 guess_encoding() 来帮助你找出答案。它并非万无一失,而且当你有大量文本时效果更好(不像这里),但它是一个合理的起点。在找到正确的编码之前,预计你需要尝试几种不同的编码:
guess_encoding(charToRaw(x1)) #> encoding confidence #> 1 ISO-8859-1 0.46 #> 2 ISO-8859-9 0.23 guess_encoding(charToRaw(x2))