R中的UTF-8文件输出

13

我正在使用Windows 7 64位系统上的R 2.15.0。我想将Unicode(CJK)文本输出到文件。

以下代码展示了将Unicode字符发送到UTF-8文件连接中写入时不起作用的情况:

rty <- file("test.txt",encoding="UTF-8")
write("在", file=rty)
close(rty)
rty <- file("test.txt",encoding="UTF-8")
scan(rty,what=character())
close(rty)

正如 scan 的输出所示:

Read 1 item 
[1] "<U+5728>"
文件没有使用UTF字符本身,而是一种符合ANSI标准的回退方式。我能否在第一次就让它正常工作(即使文本文件中有“在”这样的字符),或者我可以进行额外的魔法操作来将输出转换为Unicode,并用适当的字符替换代码字符串?
谢谢。
[更多信息:相同的代码在Cygwin、R 2.14.2中表现得正确,而在Win7上的2.14.2也出现问题。这是我的问题吗?]

【迟来的更新】问题往往与区域设置有关,而不是编码。我通过暂时更改区域设置为“适当的”内容解决了乱码输出问题。如果您拥有来自多个区域设置的语言数据,则上帝保佑您。 - Patrick
1
也许这篇文章能够帮到你。 - DJJ
5个回答

24
问题是由于一些R-Windows特殊行为引起的(使用默认系统编码/或使用某些系统写函数;我不知道具体细节,但实际上这种行为是已知的)。
在Windows上写入UTF8编码的文本,需要在类似writeLines或readLines的函数中使用useBytes=T选项:
txt <- "在"
writeLines(txt, "test.txt", useBytes=T)

readLines("test.txt", encoding="UTF-8")
[1] "在"

在这里,您可以找到一篇由Kevin Ushey撰写的非常好的文章:http://kevinushey.github.io/blog/2018/02/21/string-encoding-and-r/,深入探讨了字符串编码和R语言的相关内容。


谢谢!这对我有用。网络上有很多不完整的建议。 - Ruben

8

将UTF-8字符串保存在文本文件中:

kLogFileName <- "parser.log"
log <- function(msg="") {
  con <- file(kLogFileName, "a")
  tryCatch({
    cat(iconv(msg, to="UTF-8"), file=con, sep="\n")
  },
  finally = {
    close(con)
  })
}

这在最近的 R 版本中是否出现了问题?当我以这种方式编写文件时,仍然需要将 readLines 的编码参数设置为 "ANSI" 才能获得正确的文件内容。一个例子是,在 UTF-8 编码下,"à" 会变成 "\xe0",但使用创建文件的 readLines 时,在 ANSI 编码下会正确显示。 - dimpol
@Curious - 不,我最终使用Notepad++手动完成了它。我只需要对一个数据集中的文件进行一次操作,手动处理比继续搞R文件编码更快捷。 - dimpol

8

如果您在以后遇到这个问题,请看一下 stringi 包 (https://cran.r-project.org/web/packages/stringi/index.html)。它包含了许多函数,可以在 R 中实现一致的、跨平台的 UTF-8 字符串支持。与本主题最相关的是 stri_read_lines()stri_read_raw()stri_write_lines() 函数,即使在 Windows 上也可以一致地输入/输出 UTF-8。


0

我在处理来自数据库的UTF-8字符串时遇到了问题。

我发现唯一正确保存它们的方法是以二进制模式保存文件。

  F <- file(file.name, "wb")
  tryCatch({
    writeBin(charToRaw(the_utf8_str), F)
  },
  finally = { 
    close(F)
  })

0

我认为你遇到问题是因为write的构造方式需要输入一个对象的名称,而你似乎没有建立这样一个命名的对象。请尝试使用以下代码:

txt <- "在"
rty <- file("test.txt",encoding="UTF-8")
write(txt, file=rty)
close(rty)
rty <- file("test.txt",encoding="UTF-8")
 inp <- scan(rty,what=character())
#Read 1 item
 close(rty)
 inp
#[1] "在"

嗯,启发上面最小代码片段的原始应用程序使用了命名对象。此外,您提供的代码对我来说产生了与上面相同的结果。也许我有本地编码问题? - Patrick

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接