如何在 R Windows 中将 Unicode 字符串写入文本文件?
Posted
技术标签:
【中文标题】如何在 R Windows 中将 Unicode 字符串写入文本文件?【英文标题】:How to write Unicode string to text file in R Windows? 【发布时间】:2016-11-09 07:02:14 【问题描述】:我已经想出了如何编写 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
再搞砸一切吗?
【问题讨论】:
我自己不知道也不会用R,只是看文档,cat()
按原样输出字符串,iconv()
的mark
参数默认为true,因此调用iconv(str, to="UTF-8")
将其输出显式标记为UTF-8,然后再传递给cat()
。也许str <- "ỏ"
没有以同样的方式标记str
?您可以使用enc2utf8(str)
或Encoding(str) <- "UTF-8"
将str
显式转换并标记为UTF-8,而无需使用iconv()
。这可能会对cat()
产生影响。
【参考方案1】:
我认为在使用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")
## 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
、@ 987654333@ 即"ỏ"
)。
在"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)中的等效转换所示。
【讨论】:
【参考方案2】:不知何故,我对上述建议没有任何帮助。我在 Windows 中工作,这可能与它有关。 Windows 显然对不同的语言环境有不同的编码。但我确实发现了 Kevin Ushey 的这篇出色的帖子:
https://kevinushey.github.io/blog/2018/02/21/string-encoding-and-r/
他建议了以下对我有用的技术:
# Create temp file name
f <- tempfile(tmpdir = tempdir(), fileext = ".txt")
# Vector of crazy stuff
v <- c("Crazy stuff: Ω µ ", "β ¥ ∑ ", "≠ ≤ £ ∞ ؈ ლ ")
# Ensure strings are encoded as UTF-8
utf8 <- enc2utf8(v)
# Use native encoding on file connection
con <- file(f, open = "w", encoding = "native.enc")
# Use useBytes = TRUE
writeLines(utf8, con = con, useBytes = TRUE)
# Close connection
close(con)
# View results
x <- readLines(f, encoding = "UTF-8")
cat(x, sep = "\n")
# Crazy stuff: Ω µ
# ß ¥ ∑
# ≠ = £ 8 ؈ ლ
您可以看到,除了无限符号旋转了 90 度之外,一切都完美呈现。如果有人能弄清楚,请发表评论。
【讨论】:
关于无穷大符号,R 似乎将其解释为 ascii 代码 56,即数字 8。您可以在此处查看:utf8ToInt("∞")。还不知道为什么或如何解决它。以上是关于如何在 R Windows 中将 Unicode 字符串写入文本文件?的主要内容,如果未能解决你的问题,请参考以下文章
在 MFC C++ 中将 char 数组转换为 UNICODE
如何在MATLAB中将原始Unicode十六进制转换为Unicode表示