当您的包含有非英文字符的函数时出现编码问题

9

我正在构建自己的软件包,但由于我的软件包中的函数具有非英文(非ASCII)字符而反复遇到编码问题。

本质上,韩语字符是我软件包中许多函数的一部分。以下是一个示例函数:

library(rvest)
sampleprob <- function(url) {
  # sample url: "http://dart.fss.or.kr/dsaf001/main.do?rcpNo=20200330003851"
  result <- grepl("연결재무제표 주석", html_text(read_html(url)))
  return(result)
}

然而,在安装该软件包时我遇到了编码问题。
我创建了一个样例软件包(https://github.com/hyk0127/KorEncod/),其中只包含一个函数(如上所示),并将其上传到我的 GitHub 页面进行可重复性的演示。我运行以下代码进行安装:
library(devtools)
install_github("hyk0127/KorEncod")

以下是我看到的错误信息:

Error : (converted from warning) unable to re-encode 'hello.R' line 7
ERROR: unable to collate and parse R files for package 'KorEncod'
* removing 'C:/Users/myname/Documents/R/win-library/3.6/KorEncod'
* restoring previous 'C:/Users/myname/Documents/R/win-library/3.6/KorEncod'
Error: Failed to install 'KorEncod' from GitHub:
  (converted from warning) installation of package ‘C:/Users/myname/AppData/Local/Temp/RtmpmS5ZOe/file48c02d205c44/KorEncod_0.1.0.tar.gz’ had non-zero exit status

有关第7行的错误消息是指函数中的韩文字符。

可以使用tar.gz文件在本地安装软件包,但是由于以破碎编码识别韩文字符,所以函数无法按预期运行。

这不可能是有人尝试构建具有非英语(或非ASCII)字符的软件包的第一次,但我却找不到解决方案。非常感谢任何帮助。


我认为相关的一些信息如下:

当前的DESCRIPTION文件指定“编码:UTF-8”。

我使用了sys.setlocale将区域设置为韩文,然后又改回来,但没有用。
我还指定了@encoding UTF-8,但同样没有用。

我目前使用的是Windows操作系统,管理员语言设置为英语。我尝试过在另一台Windows操作系统的笔记本电脑上,管理员语言设置为韩语,但出现了同样的问题。


我认为devtools::session_info()中的collatectype很重要(两者都源自Sys.getlocale(),在我看来)。不幸的是,在Windows中无法像预期的那样使用Sys.setlocale(category = "LC_CTYPE" , locale=".65001"),这与Sys.setlocale(category = "LC_COLLATE" , locale=".65001")不同...这是R中Windows与UTF-8之间的老化不兼容性。 - JosefZ
2个回答

4
关键技巧是使用其Unicode编码替换非ASCII字符 - 即\uxxxx编码方式。
可以通过stringi::stri_escape_unicode()函数生成这些编码。
需要注意的是,为了通过R CMD检查,必须完全去除代码中的韩文字符,因此需要在命令行上手动复制并重新编码,然后将所有包含在软件包中的R脚本粘贴回来。
我不知道是否有可用的自动化解决方案来解决这个问题。
在提供的示例的特定用例中,unicode将如下所示:
sampleprob <- function(url) {
  # stringi::stri_escape_unicode("연결재무제표 주석") to get the \uxxxx codes
  result <- grepl("\uc5f0\uacb0\uc7ac\ubb34\uc81c\ud45c \uc8fc\uc11d", 
                  rvest::html_text(xml2::read_html(url)))
  return(result)
}
sampleprob("http://dart.fss.or.kr/dsaf001/main.do?rcpNo=20200330003851")
[1] TRUE

这可能会很麻烦,但似乎是使您的代码具有平台中立性(这是关键的CRAN要求,并因此受到R CMD检查的限制)的唯一方法。


谢谢!这种方法的一个问题是它不能以当前的形式运行。我已经尝试了这个函数并发现,当我手动将所有双反斜杠改为单反斜杠时,它可以工作(在给定的示例URL中显示“TRUE”),可能是因为只有这样它才会将Unicode读入输入而不是代码..? - Hong
以下的代码可以让 R 将 Unicode 作为输入读取。在构建软件包时,我不可避免地需要手动将表达式从 parse(text = paste0("'", stringi::stri_escape_unicode("연결재무제표 주석"), "'")) 复制粘贴到 grepl 中。grepl(parse(text = paste0("'", stringi::stri_escape_unicode("연결재무제표 주석"), "'")), html_text(read_html("http://dart.fss.or.kr/dsaf001/main.do?rcpNo=20200330003851"))) - Hong
请随意更新您的答案(为了让未来可能查看此内容的人更容易阅读)!我希望有一种更非手动的方式来构建软件包,而不是手动复制粘贴,但令人惊讶的是,这似乎是一个遥远的可能性。 - Hong
@Hong说得对,我已经扩展了答案,明确提到代码需要手动替换;这可能会很麻烦,但目前没有自动化的解决方案(至少我不知道有)。 - Jindra Lacko
顺便说一下:为了双重确认答案,我已经冒险离开了安装在甜美Unicode下的Linux系统,转而前往Windows机器(该机器运行https://en.wikipedia.org/wiki/Windows-1250以支持我的母语捷克语),但即使在代码的注释部分也遇到了韩文字符方面的严重问题。编码实在是太糟糕了! :) - Jindra Lacko

2

为了以后的价值(对于那些面临类似问题的人),您还可以通过将非ASCII字符保存在数据文件中,然后加载该值并使用它来解决此问题。

因此,将字符保存为数据文件(使用标准包文件夹名称和roxygen2包)。

# In your package, save as a separate file within .\data-raw 
kor_chrs <- list(sampleprob = "연결재무제표 주석")
usethis::use_data(kor_chrs)

然后在您的函数中加载数据并使用它们。
# This is your R file for the function within ./R folder
#' @importFrom rvest html_text
#' @importFrom xml2  read_html
#' @export
sampleprob <- function(url) {
  # sample url: "http://dart.fss.or.kr/dsaf001/main.do?rcpNo=20200330003851"
  result <- grepl(kor_chrs$sampleprob[1], html_text(read_html(url)))
  return(result)
}

这确实是一种变通方法,但在Windows系统中运行时不会出现任何问题。


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