我已经找到了如何编写Unicode字符串的方法,但是仍然对其工作原理感到困惑。
str <- "ỏ"
Encoding(str) # UTF-8
cat(str, file="no-iconv") # Written wrongly as <U+1ECF>
cat(iconv(str, to="UTF-8"), file="yes-iconv") # Written correctly as ỏ
我了解为什么
no-iconv
方法不起作用。这是因为cat
(还有writeLines
)convert the string into the native encoding first and then to the to=
encoding。在Windows上,这意味着R首先将ỏ
转换为Windows-1252
,后者无法理解ỏ
,从而导致<U+1ECF>
。我不明白的是为什么
yes-iconv
方法有效。如果我理解正确,那么iconv
所做的只是返回带有UTF-8
编码的字符串。但是str
已经在UTF-8
中了!为什么iconv
有什么不同?另外,当iconv(str, to="UTF-8")
传递给cat
时,cat
难道不应该通过首先转换为Windows-1252
再次使一切困惑吗? 最佳答案
我认为在使用str
之前将"unknown"
(的副本)的Encoding设置为cat()
并不是那么神奇,并且效果也很好。我认为应该避免在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")
## from = "" is conversion from current locale, forcing "latin1" here
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()
(大概)将字符串转换回当前语言环境时,由ojit_code隐式恢复,如步骤(3)中的等效转换。关于r - 如何在R Windows中将Unicode字符串写入文本文件?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/38237358/