简介
UTF-8 虽然也属于UNICODE一种,但其实是一种变长multiy-byte编码,可直接用char或者std:string来存储操作。也就是说兼容ascii的,而且可在同一个字符串中包含多种语言(如中日韩同时显示)。linux软件中,UTF-8是比较通用的编码方式,尤其在网络和各种开源软件以及开源库中,基本上都支持UTF-8。原因我猜是因为开源软件作者以英语为母语的占绝对多数,UTF8兼容其他语言时最省事,代码基本上不用改。
UTF8缺点:长度统计不能直接用strlen函数,汉字较多情况下比unicode或者gbk占用更多存储。微软对UTF8支持相对没那么给力,微软以UTF16和CP_ACP各国本地编码为主,例如中文的多字节就是GBK或者GB2312。
Visual Studio 2010 对UTF8的支持
源码级别的支持:
源代码本身编码(.cpp,.h文件)是直接支持UTF8的VS2010中: 菜单-》文件-》高级保存选项, 存为带bom的utf8 就可以。
编译后内存中的常量字符串编码:
缺省情况下是不会编译为UTF8的,例如,你在代码中写:
char * str ="中文";
编译后二进制exe文件中会用CP_ACP 参数缺省编译为GB2312或者GBK编码。
如果希望编译后编码仍为UTF8,可以用下面的方法:
首先打SP1补丁,
然后代码中加上:
#pragma execution_character_set("utf-8")
VS中对UTF16的支持就很好,代码中直接用L"中文",会正确编码为UTF16
调试时编码:
调试环境中,缺省支持Unicode(UTF16)和 GBK,也就是鼠标悬停时能正确的看到中文字符串,但是UTF8字符串看不到。
UTF8字符串可以用下面的方法看到:需要将要显示的字符串拉到Watch中,并在变量后面添加s8即可显示
多个不同编码库共存时解决方法
如果程序中同时用了不同编码方式的库,我的处理方式是代码中尽量用UTF8编码,
首先源代码本身用UTF8,方便代码共享,上传到网站等,
其次代码里面的常量字符串尽量能够编译成UTF8的二进制码,这样可以直接输出到一些开源库中,例如MYSQL直接支持UTF8,可以在源代码中写含有中文内容的SQL查询语句。
最后各种配置文件,文本文件也使用UTF8编码,程序里可以直接用std:string变量操作
在碰到不支持UTF8的库时,例如SFML库,基本上都会支持UNICODE, 可以调用utf8转unicode的代码转过去,VC中是MultibyteToUnicode函数STL中要特别注意local
从文件中读取中文字符串,用下面的函数去除空格会出现异常,不管是utf8编码还是gb2312编码,原因是缺少local
std::string ltrim(std::string s)
{
s.erase(s.begin(), std::find_if(s.begin(), s.end(), std::not1(std::ptr_fun<int, int>(std::isspace))));
return s;
}
自己重新定义带local的函数就没有问题:
struct my_isspace : std::unary_function<int, int>
{
int operator()(int i) const
{
return std::isspace(i, std::locale("chs"));
}
};
std::string ltrim(std::string s)
{
s.erase(s.begin(), std::find_if(s.begin(), s.end(), std::not1(my_isspace())));
return s;
}
AIML中格式化输入串,将utf8的中文用空格分割
void aiml::clean_pattern(string& pattern)
{
std::string out;
std::string ch;
for(size_t i = 0, len = 0; i < pattern.length(); i += len)
{
unsigned char byte = (unsigned)pattern[i];
if (byte >= 0xFC) //1111110x lenght 6
len = 6;
else if (byte >= 0xF8)
len = 5;
else if(byte >= 0xF0)
len = 4;
else if (byte >= 0xE0)
len = 3;
else if (byte >= 0xC0)
len = 2;
else
len = 1;
if(len == 1) //ascii
{
char c = pattern[i];
if(!isalnum(c) && c != '*' && c != '_' && c != ' ')
out += ' ';
else
out += toupper(c);
}
else //utf8 add ' ' after each word
{
ch = pattern.substr(i, len);
out += ch;
out += ' ';
}
}
pattern = out;
}