VC默认是采用ANSI编码来保存源文件。如果你在源文件中定义了常量字符串,而这个字符串中的字符又采用了其他编码,保存的时候就会提醒你“有些Unicode字符不能被保存,请采用其他编码方式保存文件”。比如我的操作系统是繁体中文,那么如下的字符串定义因为既含有繁体又有简体,就会在保存的时候报错:
TCHAR * lpStr =_T( "蘋果快乐");
改正的方法就是在菜单中选择File->Save as->Save with Encoding,采用Unicode或者UTF-8编码都可以。
下面我们将这个字符串输出到一个txt文本文件中。
condition 1:
工程属性采用Unicode字符集,源文件保存为UTF-8编码。
void test()
{
HANDLE hFile = ::CreateFile(_T("D://result.txt"),
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ,
NULL,
CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL,
NULL);
if(hFile == INVALID_HANDLE_VALUE)
{
//get the information
LPVOID lpMsgBuf; //Windows will allocate
::FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,0,
GetLastError(),MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPTSTR)&lpMsgBuf, 0, NULL );
//show
::MessageBox(0, (LPCTSTR)lpMsgBuf, _T("GetLastError"), MB_OK|MB_ICONINFORMATION );
//lpMsgBuf is the eror stirng
//release memory
::LocalFree( lpMsgBuf );
return ;
}
CFile file(hFile);
TCHAR * str1 =_T( "蘋果快乐");
int len1 = _tcslen(str1);
char * str2 = "蘋果快乐";
int len2 = (int)strlen(str2) ;
file.Write((const void*)str2, len2);
}
这里的TCHAR实际上就是wchar_t。str1指向的内存的值是3f00 5e5f 3f00 7965 1d60 3f00 0000,得到的字符串长度len1为6。而str2指向的内存的值是e8 98 8b e6 9e 9c e5 bf ab e4 b9 90 00,得到的字符串长度len2是12。
str1为什么会变成这些值?_T对字符串做了什么操作?
用记事本打开result.txt文件可以发现显示正确,并且是用UTF-8解码的。
condition 2:
工程属性采用Unicode字符集,源文件保存为Unicode编码。
TCHAR * str1 =_T( "蘋果快乐");
int len1 = _tcslen(str1);
char * str2 = "蘋果快乐";
int len2 = (int)strlen(str2) ;
file.Write((const void*)str1, len1*2);
这里的TCHAR实际上就是wchar_t。str1指向的内存的值是0b86 9c67 eb5f 504e 0000,得到的字符串长度len1为6。而str2指向的内存的值是e8 98 8b e6 9e 9c e5 bf ab e4 b9 90 00,得到的字符串长度len2是12。
str2为什么被转换成了UTF-8的编码值?
用记事本打开result.txt文件发现显示乱码,但是重新用Unicode方式打开显示正确。是否记事本要正确判读其是Unicode编码需要添加标志吗?
也可将Unicode编码转换成UTF-8编码输出:
TCHAR * str1 =_T( "Ä«ªG§Ö乐");
int len1 = _tcslen(str1);
int len2 = WideCharToMultiByte(CP_UTF8, 0, str1, len1, NULL, 0 , NULL, NULL );
char * str2 = new char[len2];
WideCharToMultiByte(CP_UTF8, 0, str1, len1, str2, len2, NULL, NULL );
file.Write((const void*)str2, len2);
delete str2;
用记事本打开result.txt文件可以发现显示正确,并且是用UTF-8解码的。
condition 3:
工程属性采用MBCS字符集,源文件保存为Unicode编码。
TCHAR * str1 =_T( "蘋果快乐");
int len1 = _tcslen(str1);
file.Write((const void*)str1, len1);
这里的TCHAR实际上就是char。在上面的condition2中知道,str1这时的值就是UTF-8编码。可直接写往txt文件,也可以转换成Unicode再写入文件。转换的步骤如下:
TCHAR * str1 =_T( "蘋果快乐");
int len1 = _tcslen(str1);
int len2 = MultiByteToWideChar(CP_UTF8, 0, str1, len1, NULL, 0);
wchar_t * str2 = new wchar_t[len2];
MultiByteToWideChar(CP_UTF8, 0, str1, len1, str2, len2);
file.Write((const void*)str2, len2*2);
delete str2;
用记事本打开result.txt文件发现显示乱码,重新用Unicode方式打开显示正确。
condition 4:
工程属性采用MBCS字符集,源文件保存为UTF-8编码。
与condition3类似,可以直接将UTF-8编码写入文件,也可转换成Unicode写入。
MultiByteToWideChar&WideCharToMutiByte
See MSDN
CodePage常用的是CP_ACP(ANSI),CP_UTF8(UTF-8)
注意先计算所需的长度(此时无需给出dest的pointer和length),再分配空间,最后要释放
*****************************************小李飞刀再飞刀**************************************************
版权所有,转载请注明
*****************************************小李飞刀再飞刀**************************************************