Unicode & UTF-8

来源:互联网 发布:网络大电影的盈利 编辑:程序博客网 时间:2024/04/29 15:56

 http://hi.baidu.com/%D0%A1%C0%EE%B7%C9%B5%B6%D4%D9%B7%C9%B5%B6/blog/item/1541356f34ef03d281cb4aad.html

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),再分配空间,最后要释放

*****************************************小李飞刀再飞刀**************************************************

                                                           版权所有,转载请注明

*****************************************小李飞刀再飞刀**************************************************

 

原创粉丝点击