如何使用Rcpp读取Windows-1252文件?

时间:2015-07-28 08:15:17

标签: c++ locale rcpp windows-1252

我想在将文件与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

我还尝试过&#34; Swedish_Sweden.1252&#34;这是我的系统默认无效。我试过#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)是否构建了语言环境支持,this SO question指出了这种可能性。如果有任何争论,除了&#34;&#34;或&#34; C&#34;与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倍(用microbenchmark检查):

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

0 个答案:

没有答案