Как да прочета Windows-1252 файл с помощта на Rcpp?

Искам да принудя входния формат при четене на файл в Windows-1252 кодиране заедно с Rcpp. Имам нужда от това, тъй като превключвам между среди на 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).

Актуализация:

След като се задълбочих малко в това, не съм сигурен дали gcc (v. 4.6.3) в RTools (v. 3.3) е изграден с локална поддръжка, този SO въпрос сочи тази възможност. Ако има някакъв аргумент освен "" или "C" работи със std::locale(), би било интересно да знам, опитах още няколко алтернативи, но изглежда нищо не работи.

Резервно решение

Не съм напълно доволен, но изглежда, че използването на base::iconv() коригира всички проблеми със знаците, независимо от оригиналния формат, много благодарение на from="WINDOWS-1252"argument, който принуждава знаците да бъдат интерпретирани в правилната форма, т.е. ако искаме да останем в 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")
}

person Max Gordon    schedule 28.07.2015    source източник
comment
Можете ли да опитате Rcpp 0.12.0, който току-що беше пуснат? Той добави известна поддръжка на кодиране.   -  person Dirk Eddelbuettel    schedule 28.07.2015
comment
@DirkEddelbuettel: Благодаря, но за съжаление получавам същата грешка. Не съм сигурен дали синтаксисът изобщо е правилен, т.е. дали е някоя от предложените по-горе алтернативи? Както писах, има усилване:: локал, който трябва да бъде създаден за справяне с този тип проблеми, но изглежда, че локалът не е включен в Windows, тъй като получавам фатална грешка: boost/locale.hpp: Няма такъв файл или директория докато други части се зареждат добре (напр. #include <boost/algorithm/string.hpp>)   -  person Max Gordon    schedule 28.07.2015