D
Hier mal ein Beispiel das praktisch funktioniert:
const std::string getCharset()
{
std::string Locale;
std::string charset;
if (!setlocale(LC_ALL, "")) {
fprintf(stderr, "Can't set the specified locale! Check LANG, LC_CTYPE, LC_ALL.\n");
return(std::string());
//TODO: throw exception
}
else{
Locale = setlocale(LC_CTYPE,NULL);
std::cout<<"Locale LC_CTYPE is: "<<Locale<<std::endl;
}
std::string LocaleLower = convertLowercase(Locale);
std::cout<<" actual CTYPE Locale (in lowecase) is: "<<LocaleLower<<std::endl;
int pinLoc = countOccurence(Locale,std::string("."));
int ulinLoc = coutOccurence(Locale,std::string("_"));
std::cout<<"found . "<<pinLoc<<" times, "<<"found _ "<<ulinLoc<<" times in "<<Locale<<std::endl;
std::string codepage;
if(pinLoc == 1){
size_t pos = Locale.find(std::string("."),0);
codepage = Locale.substr(pos+1,Locale.length()-pos-1); //TODO: anhängsel @... z.B. @euro
std::cout<<"codepage is: "<<codepage<<std::endl;
}
else{
std::cout<<"unable to find codepage in Locale!"<<std::endl;
}
if(ulinLoc == 1){
size_t posul = Locale.find(std::string("_"),0);
std::string Language = Locale.substr(0,posul);
std::string Country;
if(pinLoc == 1){
size_t posp = Locale.find(std::string("."),0);
Country = Locale.substr(posul+1,posp-posul-1);
}
else{
Country = Locale.substr(posul+1,Locale.length()-posul-1);//TODO: anhängsel @... z.B. @euro
}
std::cout<<"Country is: "<<Country<<", Language is: "<<Language<<std::endl;
}
else{
std::cout<<"unable to find Country/Language in Locale!"<<std::endl;
}
if(codepage.empty())
return(std::string("unkown"));
if(codepage == std::string("1252"))
charset = std::string("CP1252");
else if(codepage == std::string("UTF-8"))
charset = std::string("UTF-8");
else
charset = std::string("unkown");
#if defined(_WIN32) || defined(WIN32) || defined (WIN) || defined(_WIN) || defined (_WIN64) || defined (WIN64)
std::string consoleCodepage;
char buffer[512];
memset(buffer,0,sizeof(buffer));
FILE *fp = popen("chcp", "r" );
if(fgets( buffer, sizeof(buffer), fp ) != NULL) {
consoleCodepage = std::string(buffer);
}
pclose( fp );
std::cout<<"consoleCodepage before: "<<consoleCodepage<<std::endl;
if(system(std::string("chcp ").append(codepage).c_str())){
std::cout<<"cannot set console Codepage to "<<codepage<<std::endl;
}
else{
memset(buffer,0,sizeof(buffer));
fp = popen("chcp", "r" );
if ( fgets( buffer, sizeof(buffer), fp ) != NULL ) {
consoleCodepage = std::string(buffer);
}
pclose( fp );
std::cout<<"consoleCodepage after: "<<consoleCodepage<<std::endl;
}
#else
//Linux: Terminal Encoding == LC_CTYPE, hopefully ever....
// # OTHER OS?
#endif
return(charset);
}
Ist nicht wirklich schön, unterstützt erst zwei Codierungen, aber ihr seht wohin die Reise gehen soll..
Edit: Für die die es proktisch probieren wollen, hier noch die hilfsfunktionen:
int countOccurence(const std::string &searchin, const std::string &searchfor)
{
size_t found = 0;
int occ = 0;
do{
found = searchin.find(searchfor,found+1);
if (found != std::string::npos){
++occ;
}
}while(found != std::string::npos);
return(occ);
}
const std::string convertLowercase(const std::string &inStr)
{
std::locale loc;
size_t len = inStr.length();
char stringData[len];
strncpy(stringData, inStr.c_str(),len);
stringData[len]=0;
std::cout << "stringData: "<<stringData<<std::endl;
std::use_facet< std::ctype<char> >(loc).tolower(stringData, stringData+sizeof(stringData));
return stringData;
}