3

我想在将文件与 Rcpp 一起读入 Windows-1252 编码时强制输入格式。我需要这个,因为我在 Linux/Windows 环境之间切换并且文件始终采用 1252 编码。

我如何使其适应工作:

String readFile(std::string path) {
  std::ifstream t(path.c_str());
  if (!t.good()){
    std::string error_msg = "Failed to open file ";
    error_msg += "'" + path + "'";
    ::Rf_error(error_msg.c_str());
  }

  const std::locale& locale = std::locale("sv_SE.1252");
  t.imbue(locale); 
  std::stringstream ss;
  ss << t.rdbuf();
  return ss.str();
}

以上失败:

Error in eval(expr, envir, enclos) : 
  locale::facet::_S_create_c_locale name not valid

我也尝试过使用“Swedish_Sweden.1252”,这是我系统的默认设置,但无济于事。我已经尝试过#include <boost/locale.hpp>,但这似乎在 Rcpp (v 0.12.0)/BH boost (v. 1.58.0-1) 中不可用。

更新:

在深入研究之后,我不确定 RTools (v. 3.3) 中的 gcc (v. 4.6.3) 是否在语言环境支持下构建,这个 SO question指出了这种可能性。如果除了 "" 或 "C" 之外有任何参数可与 std::locale() 一起使用,知道会很有趣,我尝试了更多替代方案,但似乎没有任何效果。

后备解决方案

我并不完全满意,但似乎使用base::iconv()修复了字符的任何问题,无论原始格式如何,这要归功于from="WINDOWS-1252"强制以正确形式解释字符的参数,即如果我们想留在 Rcpp 我们可以简单做:

String readFile(std::string path) {
  std::ifstream t(path.c_str());
  if (!t.good()){
    std::string error_msg = "Failed to open file ";
    error_msg += "'" + path + "'";
    ::Rf_error(error_msg.c_str());
  }

  const std::locale& locale = std::locale("sv_SE.1252");
  t.imbue(locale); 
  std::stringstream ss;
  ss << t.rdbuf();
  Rcpp::StringVector ret = ss.str();

  Environment base("package:base");
  Function iconv = base["iconv"];

  ret = iconv(ret, Named("from","WINDOWS-1252"),Named("to","UTF8"));

  return ret;
}

请注意,最好将函数包装在 R 中,而不是从 C++ 中获取函数然后从那里调用它,它既减少了代码,又将性能提高了 2 倍(通过微基准检查):

readFileWrapper <- function(path){
   ret <- readFile(path)
   iconv(ret, from = "WINDOWS-1252", to = "UTF8")
}
4

0 回答 0