最近看公司的一些代码,发现一些地方调用了std::locale::global(locale("")); (c++) 和 setlocale(LC_ALL, "");(c)。
如多字节字符转换为宽字符:
setlocale(LC_ALL, "");
const size_t len = byte_size / sizeof(wchar_t);
size_t res = mbstowcs(buf, info, len);
ifstream读取文本:
std::locale::global(locale(""));
std::ifstream in(filePath, std::ios::in);
std::locale::global(locale("C"));
概念:
C/C++程序中,locale(即系统区域设置,即国家或地区设置)将决定程序所使用的当前语言编码、日期格式、数字格式及其它与区域有关的设置,locale设置的正确与否将影响到程序中字符串处理(wchar_t如何输出、strftime()的格式等)。因此,对于每一个程序,都应该慎重处理locale设置。
C locale和C++ locale是独立的。C locale用setlocale(LC_CTYPE, “”)初始化,
C++ locale用std::locale::global(std::locale(“”))初始化。这样就可以根据当前系统的运行环境正确设置locale。
原因:
vs2005中std::fstream打开文件的函数中,传入的const char* 文件路径是作为多字节首先被mbstowcs 转换成宽字节,然后在转发给Unicode版本的API进行实际的打开文件操作。
如果路径中包含中文,对于mbstowcs 函数来说,它需要知道多字节的编码类型才能正确的将其转换为宽字节的Unicode,这个编码类型没有通过函数的参数列表传入,只能依赖全局的locale。全局的locale默认没有使用系统当前的语言,而是设置为"C" locale。
解决:
在调用mbstowcs 或使用它的函数前,先用setlocale将全局默认locale设置为当前系统的locale:
setlocale(LC_ALL, "");
如果是非中文系统上转GBK编码,就需要指定中文locale:
setlocale(LC_ALL, "chs");
总结:
std::locale和文本的编码格式无关,只是在文件路径有中文的情况下需要初始化。和ifstream转换中文路径的实现有关。