如何在 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,无法理解,导致&lt;U+1ECF&gt;

我不明白为什么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 &lt;- "ỏ" 没有以同样的方式标记str?您可以使用enc2utf8(str)Encoding(str) &lt;- "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" 应该是正确的(字节序列 0xe10xbb、@ 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表示

如何在 Unicode 中将字符串设置为大写/小写?

Unicode不等号在Windows环境中的R中变成等号

如何在 C++ 中将字符的十进制代码转换为 Unicode 字符串?

在 C# 中将上标转换为 Unicode [关闭]