乱码包含两种一种是我们保存的文件在不同的系统中打开时候是乱码的,一种是在网络通信的时候接收的数据时候乱码的。
第一种解决方法
Visual Studio (中文版)默认保存的文本文件是GB2312
编码(代码页936)的,默认的行尾(End of line)是CRLF的。
如果仅仅是在windows下开发问题也不大,但是涉及到跨平台开发的时候,就不是很满意了。
VS本身的 文件 -> 高级保存选项 中是可以选择保存的编码和行尾的,但是不支持为默认的。
还有一个问题是cl
编译的时候,对utf-8
格式支持不好(需要添加/source-charset:utf-8
选项,默认是当作本地字符集的),对于带BOM
标记的文件则没有问题。
所以我们在项目中统一规定使用UTF-8 with BOM
编码,行尾为LF
(\n)。
这里介绍两个插件
ForceUTF8 (with BOM)
这个插件还有两个版本,一个是带BOM
的,一个是不带的。
插件是开源的,代码很简单。就是在文档保存的时候,判断是否是文本文件。如果是的话,那就先转编码为UTF-8 with BOM
,再写入文件。
下载地址 https://marketplace.visualstudio.com/items?itemName=jz5.ForceUTF8withBOM
其实可以直接在这个项目上改,在保存文件前把\r\n
、\r
、\n
都替换为\n
即可(要注意替换次序)。
Line Endings Unifier
这个插件用来统一行尾。
可以设置针对的文件和目标行尾。它也是开源的。
下载地址 https://marketplace.visualstudio.com/items?itemName=JakubBielawa.LineEndingsUnifier
第二种:
当我们接收到含有中文的字符串乱码的时候如果能保证发过来的是utf-8
这里我们可以把utf-8转为vs使用的编码类型
这里提供两个函数用于相互转换:
1. utf8转std::string
转换过程:先将utf8转双字节Unicode编码,再通过WideCharToMultiByte将宽字符转换为多字节。
//-----------------------------------------------------------------------
std::string UTF8_To_string(const std::string & str)
{
int nwLen = MultiByteToWideChar(CP_UTF8, 0, str.c_str(), -1, NULL, 0);
wchar_t * pwBuf = new wchar_t[nwLen + 1];//一定要加1,不然会出现尾巴
memset(pwBuf, 0, nwLen * 2 + 2);
MultiByteToWideChar(CP_UTF8, 0, str.c_str(), str.length(), pwBuf, nwLen);
int nLen = WideCharToMultiByte(CP_ACP, 0, pwBuf, -1, NULL, NULL, NULL, NULL);
char * pBuf = new char[nLen + 1];
memset(pBuf, 0, nLen + 1);
WideCharToMultiByte(CP_ACP, 0, pwBuf, nwLen, pBuf, nLen, NULL, NULL);
std::string retStr = pBuf;
delete []pBuf;
delete []pwBuf;
pBuf = NULL;
pwBuf = NULL;
return retStr;
}
// translate ascii characters to utf-8 characters
2.std::string转utf8字符串
转换过程:与1过程相反
//------------------------------------------------------------------------
std::string string_To_UTF8(const std::string & str)
{
int nwLen = ::MultiByteToWideChar(CP_ACP, 0, str.c_str(), -1, NULL, 0);
wchar_t * pwBuf = new wchar_t[nwLen + 1];//一定要加1,不然会出现尾巴
ZeroMemory(pwBuf, nwLen * 2 + 2);
::MultiByteToWideChar(CP_ACP, 0, str.c_str(), str.length(), pwBuf, nwLen);
int nLen = ::WideCharToMultiByte(CP_UTF8, 0, pwBuf, -1, NULL, NULL, NULL, NULL);
char * pBuf = new char[nLen + 1];
ZeroMemory(pBuf, nLen + 1);
::WideCharToMultiByte(CP_UTF8, 0, pwBuf, nwLen, pBuf, nLen, NULL, NULL);
std::string retStr(pBuf);
delete []pwBuf;
delete []pBuf;
pwBuf = NULL;
pBuf = NULL;
return retStr;
}