首页 > 解决方案 > 如何在 R 的文本文件中保存非英文字符?

问题描述

标签: runicode

解决方案


在将文件写入为 R for Windows 中的 UTF-8 编码的文章中找到了一种解决方法(那里有详尽的解释):

BOM <- charToRaw('\xEF\xBB\xBF')

writeUtf8 <- function(x, file, bom=F) {
  Encoding(x) <- "UTF-8"                  # superabundant?
  con <- file(file, "wb")
  if(bom) writeBin(BOM, con, endian="little")
  writeBin(charToRaw(x), con, endian="little")
  close(con)
}

data <- c("चौपाई&quot;)
writeUtf8(x=data, file="data.txt")

解释(从上述文章中复制和粘贴,部分截断):

Windows 与其他操作系统的区别

我想说尽可能简单。Windows 选择多种语言集之一,然而,Linux 和 Mac OS 选择 UTF-8 集的一种语言子集。通过这种差异,Windows 会忘记未选择语言的字符,而其他操作系统会记住所有语言的字符。

Windows 上的问题

将文本写入文件时,无法处理未选择区域设置语言的字符。其中一些被转换为类似(但不正确!)的字符,而另一些被写为转义格式,例如 <U+222D>。

请注意,R 不对这个问题负责。因为操作系统的切换语言架构正在产生问题。

...当 R 在 Windows 上将 UTF-8 文本写入文件时,会修改不受支持语言的字符。相反,所有字符在 Mac OS 中都正确写入。

使用二进制

这个问题有一个解决方案。编写二进制文件而不是文本文件可以解决这个问题。在 Windows 中处理 UTF-8 文件的所有应用程序都使用相同的技巧。

物料清单

不应在 UTF-8 文件中使用 BOM。这就是 Linux 和 Mac OS 正在做的事情。但是 Windows 记事本和一些应用程序使用 BOM。因此,尽管语法错误,仍需要处理 BOM。

BOM 是放置在文本文件开头的 3 字节字符,但由于 R 不使用 BOM,因此应在读取时将其删除。

BOM <- charToRaw('\xEF\xBB\xBF')

写入 UTF-8 文件

writeUtf8 <- function(x, file, bom=F) {
  con <- file(file, "wb")
  if(bom) writeBin(BOM, con, endian="little")
  writeBin(charToRaw(x), con, endian="little")
  close(con)
}

将 UTF-8 字符串指定为 x=,将要写入的文件名指定为 file=。如果您只想使用 Windows 记事本读取文件,通过bom=T选项添加 BOM 是一个不错的选择。请注意,这是一个最小脚本,并不意味着要编写一个非常大的文件。

编辑

请注意在和函数中添加的编码内容 ( ):Encoding(result) <- "UTF-8"readUtf8readUtf8Text

读取 UTF-8 很容易,因为像 readLines 这样的函数具有 encoding= 接受 UTF-8 的选项。

readUtf8Text <- function(file) {
  con <- file(file, 'rt')
  result <- readLines(con, encoding='utf-8')
  close(con)
  Encoding(result) <- "UTF-8"                # important
  result
}

如果您想读取由 Windows 标准应用程序(如记事本)保存的 UTF-8 文件,您可能会遇到麻烦。由于 Windows 记事本在写入 UTF-8 文件时会附加 BOM,因此您必须删除 R 上的 BOM。否则 BOM 将在字符串的开头显示为损坏的字符。

现在,R 3.0.0 支持 UTF-8-BOM 编码来移除 BOM。但是,如果您想暂时使用 R 2.15.3,则必须手动删除 BOM。以下代码将 UTF-8 文件读取为二进制文件并删除 BOM。

请注意,这是一个最小的脚本,并不意味着读取一个非常大的文件。

readUtf8 <- function(file) {
  size <- file.info(file)$size
  con <- file(file, "rb")
  x <- readBin(con, raw(), size, endian="little")
  close(con)
  pstart <- ifelse(all(x[1:3]==BOM), 4, 1)
  pend <- length(x)
  result <- rawToChar(x[pstart:pend])
  Encoding(result) <- "UTF-8"               # important
  result
}

结果

RStudio1.3 和RGui4.0.1 ( Windows 10/64bit, i.e. platform x86_64-w64-mingw32`) 中测试:

> data <- c("चौपाई&quot;)
> writeUtf8(x=data, file="data.txt")
> 
> data
[1] "चौपाई&quot;
>
> readUtf8Text(file="data.txt")
[1] "चौपाई&quot;
>
> readUtf8(file="data.txt")
[1] "चौपाई&quot;

为了证明Encoding(result) <- "UTF-8"在两个读取功能中防止mojibake的重要性:

> file <- "data.txt"
> con <- file(file, 'rt')
> result <- readLines(con, encoding='utf-8')
> close(con)
> result                                       # mojibake
[1] "चौपाई"
> Encoding(result) <- "UTF-8"
> result
[1] "चौपाई&quot;
> 

推荐阅读