Как прочитать файл 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) построен с поддержкой локали, этот ТАК вопрос указывает на такую ​​возможность. Если есть какой-либо аргумент, кроме "" или "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 раза (проверено с помощью microbenchmark):

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: Спасибо, но, к сожалению, я получаю ту же ошибку. Я не уверен, что синтаксис вообще правильный, т.е. это какая-либо из предложенных выше альтернатив? Как я уже писал, есть boost:: локаль, которая должна быть создана для решения проблем такого типа, но кажется, что локаль не включена в Windows, так как я получаю фатальную ошибку: boost/locale.hpp: Нет такого файла или каталога в то время как другие части загружаются нормально (например, #include <boost/algorithm/string.hpp>)   -  person Max Gordon    schedule 28.07.2015