我认为在使用
cat()
之前,将(复制的)
str
的编码设置为
"unknown"
不仅没有魔法,而且同样有效。我认为这应该避免
cat()
中任何不必要的字符集转换。
以下是一个扩展示例,以演示我认为在原始示例中发生的情况:
print_info <- function(x) {
print(x)
print(Encoding(x))
str(x)
print(charToRaw(x))
}
cat("(1) Original string (UTF-8)\n")
str <- "\xe1\xbb\x8f"
Encoding(str) <- "UTF-8"
print_info(str)
cat(str, file="no-iconv")
cat("\n(2) Conversion to UTF-8, wrong input encoding (latin1)\n")
str2 <- iconv(str, from="latin1", to="UTF-8")
print_info(str2)
cat(str2, file="yes-iconv")
cat("\n(3) Converting (2) explicitly to latin1\n")
str3 <- iconv(str2, from="UTF-8", to="latin1")
print_info(str3)
cat(str3, file="latin")
cat("\n(4) Setting encoding of (1) to \"unknown\"\n")
str4 <- str
Encoding(str4) <- "unknown"
print_info(str4)
cat(str4, file="unknown")
在Windows上,R使用的是“Latin-1”区域设置(参见?l10n_info),输出文件“yes-iconv”,“latin”和“unknown”应该是正确的(字节序列0xe1、0xbb、0x8f即“ỏ”)。
在“UTF-8”区域设置下,文件“no-iconv”和“unknown”应该是正确的。
使用运行于Wine上的R 3.3.2 64位Windows版本的示例代码的输出结果如下:
(1) Original string (UTF-8)
[1] "ỏ"
[1] "UTF-8"
chr "<U+1ECF>""| __truncated__
[1] e1 bb 8f
(2) Conversion to UTF-8, wrong input encoding (latin1)
[1] "á»\u008f"
[1] "UTF-8"
chr "á»\u008f"
[1] c3 a1 c2 bb c2 8f
(3) Converting (2) explicitly to latin1
[1] "á»"
[1] "latin1"
chr "á»"
[1] e1 bb 8f
(4) Setting encoding of (1) to "unknown"
[1] "á»"
[1] "unknown"
chr "á»"
[1] e1 bb 8f
在原始的例子中,
iconv()
使用默认的
from = ""
参数,这意味着从当前语言环境进行转换,实际上是"latin1"。因为
str
的编码实际上是"UTF-8",所以在步骤(2)中字符串的字节表示被扭曲了,但随后由
cat()
隐式地恢复,当它将字符串转换回当前语言环境时,正如步骤(3)中所示的等效转换。