Искам да принудя входния формат при четене на файл в 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")
}
#include <boost/algorithm/string.hpp>
) - person Max Gordon   schedule 28.07.2015