多字节字符项目和unicode字符项目之间的转换

时间:2021-02-13 22:26:22

1: 首先更改项目属性为多字节字符集.

2: 对于所有 L"字符串", 去掉L, 或改为=> _T("字符串")   

    ps1: _T是个自动替换的宏可以根据编译条件的不同替换成不同的东西

    ps2:若想使用_T,要先包含<tchar.h>文件

3: 替换所有的 WCHAR  TCHAR

4: 替换所有的Unicode函数为非Unicode函数 eg _wsplitpath_s => _splitpath_s

     ps1: 最好使用那些能够根据编译条件自动替换的函数.像所有的Windows API, 他都提供了两个版本可以根据编译条件自动替换

5: 对于那些仅提供Unicode版本的函数那么就只要修改我们的参数以适应.

    eg: CImage::FromFile( CString str)=>CImage::FromFile( CString str)

    ==>    eg: CImage::FromFile( CString str)=>CImage::FromFile( CString str.AllocSysString() )

6: 有个MultiChar***的函数也可以把多字节字符转换为unicode字符.

 

PS :多字节字符集MBCS的含义是对于ANSI字符仅占用一个字节对于非ANSI字符比如中文,日文都占用两个字节

      由于ANSI字符有128所以, ANSI字符的bit最高位为0, bit最高位为1就表示是个双字节字符了.

      多字节字符集有时也称为 ANSI字符这是因为 MSDC兼容ANSI的表示.

PS2: 对于Unicode字符串结尾符为0x0000, 对于ansi字符串结尾符为0x00, 对于MBCS,结尾福为 0x00(这个0x00ANSI的一个字符, MSCB肯定兼容了)

 

对于 char * pStr = "ddd";

ANSI函数 strlen: 返回 5

MBCS函数 _mbslen: 返回 4, 它能识别到中是一个字符(双字节)

UNICODE函数 wcslen: 报错无法将char*类型转化为 w_char*类型!!!

 

Q UNICODE字符串如何显示 

如果程序定义了_UNICODE宏直接用 

WCHAR *str=L"unicodestring"; 

TextOut(0,0str); 

否则就需要转换类型 

#include <comdef.h> 

WCHAR *str=L"unicodestring"; 

bstr_t str1=str; 

TextOut(0,0(char*)str1); 

 

如何实现ANSIUNICODE的相互转换 

ANSI转换到Unicode 

(1)通过L这个宏来实现,例如: CLSIDFromProgID(L"MAPI.Folder",&clsid); 

(2)通过MultiByteToWideChar函数实现转换,例如

char *szProgID = "MAPI.Folder"; 

WCHAR szWideProgID[128]; 

CLSID clsid; 

long lLen = MultiByteToWideChar(CP_ACP,0,szProgID,strlen(szProgID),szWideProgID,sizeof(szWideProgID)); 

szWideProgID[lLen] = '\0'; 

(3)通过A2W宏来实现,例如

USES_CONVERSION; 

CLSIDFromProgID( A2W(szProgID),&clsid); 

 

Unicode转换到ANSI 

(1)使用WideCharToMultiByte,例如

// 假设已经有了一个Unicode  wszSomeString... 

char szANSIString [MAX_PATH]; 

WideCharToMultiByte ( CP_ACP, WC_COMPOSITECHECK, wszSomeString, -1,szANSIString, sizeof(szANSIString), NULL, NULL ); 

(2)使用W2A宏来实现,例如

USES_CONVERSION; 

pTemp=W2A(wszSomeString); 

 

注意在转换时可能存在的问题: 

 ANSIUNICODE,如果使用A2WMultiByteToWideChar(第一个参数是CP_ACP)的话,是根据系统默认的转码表,把转 入的ANSI字符串看作Multi-Bytes字符串处理的,如果是中文(中文windows默认就是中文),一个大于0x87byte可能和下一 byte一起被看作一个汉字,然后根据汉字的Unicode编码转换为相同的Unicode汉字,如果找不到相应的编码,一般就用一个默认的字符来取代它 (一般是问号,由此看,如果随便把一段数据给他转,转化很复杂而且极可能不可逆,而且你加密过的ANSI码是相当混乱的有很多〉0x87 byte,转换就变得不可逆了。 

建议自己直接就这样写: 

CHAR lpANSI[COUNT]; 

WCHAR lpUnicode[COUNT]; 

int i = 0; 

while(lpANSI[i] != '\0' ) { 

lpUnicode[i] = (WCHAR)lpANSI[i]; 

lpUnicode[i] = L'\0'; 

 后按相同的方法转回来,因为对于0~0x87ANSI字符串,对应的Unicode码就是相同的16位值,至于其他的,你的字符串反正加了密,没必要转 换成显示出来是一样的字符,就按同样的方法处理了,其实如果中间的字符串不用显示或别的,直接reutrn (LPWSTR)lpANSI;过去也可以反正接受的时候自己清楚就可以了。 

 

如何让程序支持UNICODE 

NT 系统的内核是unicode代码,通常vc分创建的工程默认都是ansi代码(可以兼容win9x,ntansi程式在调用windows API的时系统实际又进行了一次ansiunicode的代码转化,MoveWindowA实际上又调用MoveWindowW.如果以我们的程序 不考虑win9x(早晚是明日黄花)的话,直接用unicode编译,那么程式的代码执行效率一定能增色不少.具体 

(0).vc编译选项 ,vc7.0以上在工程的属性页中的字符集选上"使用 Unicode 字符集"即可,在vc6.0下可能麻烦一点,得先把vc运行库的unicode版本复制到vc路径下,一般都是和xxx.libansi对应 xxxU.lib,默认装vc时是不会装的,将工程属性 

(0).1.改语言定义

project settings"C++"页中的"preprocessor definitions"中改_MBCS_UNICODE 

(0).2.改入口函数

"link"页中的"project Options"加入/entry:"wWinMainCRTStartup"即可

 

(1)在代码上,处理字符中的多用TCHAR.H中的宏,strcpy_tcscpy代替,TCHARchar, 

TCHAR m_mystr[]=_T("xxxx")代替 char m_mystr[]="xxxx"; 

(2)注意调试UNICODE程序时,需要在安装时VC选择所有选项,否则会缺少动态库和相应的.lib文件 

 

如何取得一个既包含单字节字符又包含双字节字符的字符串的字符个数? 

可以调用Microsoft Visual C++的运行期库包含函数_mbslen来操作多字节(既包括单字节也包括双字节)字符串。 

调用strlen函数,无法真正了解字符串中究竟有多少字符,它只能告诉你到达结尾的0之前有多少个字节。 

 

如何对DBCS(双字节字符集)字符串进行操作? 

函数 描述 

PTSTR CharNext  LPCTSTR 返回字符串中下一个字符的地址 

PTSTR CharPrev  LPCTSTR, LPCTSTR ); 返回字符串中上一个字符的地址 

BOOL IsDBCSLeadByte( BYTE ) 如果该字节是DBCS字符的第一个字节,则返回非0 

 

为什么要使用Unicode 

(1) 可以很容易地在不同语言之间进行数据交换。 

(2) 使你能够分配支持所有语言的单个二进制.exe文件或DLL文件。 

(3) 提高应用程序的运行效率。 

Windows 2000是使用Unicode从头进行开发的,如果调用任何一个Windows函数并给它传递一个ANSI字符串,那么系统首先要将字符串转换成 Unicode,然后将Unicode字符串传递给操作系统。如果希望函数返回ANSI字符串,系统就会首先将Unicode字符串转换成ANSI字符 串,然后将结果返回给你的应用程序。进行这些字符串的转换需要占用系统的时间和内存。通过从头开始用Unicode来开发应用程序,就能够使你的应用程序 更加有效地运行。 

Windows CE 本身就是使用Unicode的一种操作系统,完全不支持ANSI Windows函数 

Windows 98 只支持ANSI,只能为ANSI开发应用程序。 

Microsoft公司将COM16Windows转换成Win32时,公司决定需要字符串的所有COM接口方法都只能接受Unicode字符串。 

 

如何编写Unicode源代码? 

Microsoft 公司为Unicode设计了WindowsAPI,这样,可以尽量减少代码的影响。实际上,可以编写单个源代码文件,以便使用或者不使用Unicode 对它进行编译。只需要定义两个宏(UNICODE_UNICODE),就可以修改然后重新编译该源文件。 

_UNICODE宏用于C运行期头文件,而UNICODE宏则用于Windows头文件。当编译源代码模块时,通常必须同时定义这两个宏。 

 

Q Windows定义的Unicode数据类型有哪些? 

数据类型 说明 

WCHAR Unicode字符 

PWSTR 指向Unicode字符串的指针 

PCWSTR 指向一个恒定的Unicode字符串的指针 

对应的ANSI数据类型为CHARLPSTRLPCSTR 

ANSI/Unicode通用数据类型为TCHARPTSTR,LPCTSTR 

 

如何对Unicode进行操作? 

字符集 特性 实例 

ANSI 操作函数以str开头 strcpy 

Unicode 操作函数以wcs开头 wcscpy 

MBCS 操作函数以_mbs开头 _mbscpy 

ANSI/Unicode 操作函数以_tcs开头 _tcscpyC运行期库) 

ANSI/Unicode 操作函数以lstr开头 lstrcpyWindows函数) 

所有新的和未过时的函数在Windows2000中都同时拥有ANSIUnicode两个版本。ANSI版本函数结尾以A表示;Unicode版本函数结尾以W表示。Windows会如下定义: 

#ifdef UNICODE 

#define CreateWindowEx CreateWindowExW 

#else 

#define CreateWindowEx CreateWindowExA 

#endif // !UNICODE 

 

如何表示Unicode字符串常量? 

字符集 实例 

ANSI “string” 

Unicode L“string” 

ANSI/Unicode T(“string”)_TEXT(“string”)if( szError[0] == _TEXT(‘J’) ){ } 

 

为什么应当尽量使用操作系统函数? 

这将有助于稍稍提高应用程序的运行性能,因为操作系统字符串函数常常被大型应用程序比如操作系统的外壳进程Explorer.exe所使用。由于这些函数使用得很多,因此,在应用程序运行时,它们可能已经被装入RAM 

如:StrCatStrChrStrCmpStrCpy等。 

 

如何编写符合ANSIUnicode的应用程序? 

(1) 将文本串视为字符数组,而不是chars数组或字节数组。 

 

 

(2) 将通用数据类型(如TCHARPTSTR)用于文本字符和字符串。 

(3) 将显式数据类型(如BYTEPBYTE)用于字节、字节指针和数据缓存。 

(4) TEXT宏用于原义字符和字符串。 

(5) 执行全局性替换(例如用PTSTR替换PSTR)。 

(6) 修改字符串运算问题。例如函数通常希望在字符中传递一个缓存的大小,而不是字节。这意味着不应该传递sizeof(szBuffer),而应该传递 sizeof(szBuffer)/sizeof(TCHAR)。另外,如果需要为字符串分配一个内存块,并且拥有该字符串中的字符数目,那么请记住要 按字节来分配内存。这就是说,应该调用 

malloc(nCharacters *sizeof(TCHAR)),而不是调用malloc(nCharacters) 

 

如何对字符串进行有选择的比较? 

通过调用CompareString来实现。 

标志 含义 

NORM_IGNORECASE 忽略字母的大小写 

NORM_IGNOREKANATYPE 不区分平假名与片假名字符 

NORM_IGNORENONSPACE 忽略无间隔字符 

NORM_IGNORESYMBOLS 忽略符号 

NORM_IGNOREWIDTH 不区分单字节字符与作为双字节字符的同一个字符 

SORT_STRINGSORT 将标点符号作为普通符号来处理 

 

如何判断一个文本文件是ANSI还是Unicode 

判断如果文本文件的开头两个字节是0xFF0xFE,那么就是Unicode,否则是ANSI 

 

如何判断一段字符串是ANSI还是Unicode 

IsTextUnicode进行判断。IsTextUnicode使用一系列统计方法和定性方法,以便猜测缓存的内容。由于这不是一种确切的科学方法,因此 IsTextUnicode有可能返回不正确的结果。 

 

如何在UnicodeANSI之间转换字符串? 

Windows函数MultiByteToWideChar用于将多字节字符串转换成宽字符串;函数WideCharToMultiByte将宽字符串转换成等价的多字节字符串。 

 

如何得到汉字的Unicode编码 

#include "comdef.h" 

char *str1="你好"; 

_bstr_t str=str1; 

WCHAR *str2=str; 

str2就是你要的UNICODE 

 

如何实现#21592#24037#36873#25321这种编码与汉字之间的转换? 

CString str="#21592#24037#36873#25321"; 

str+='#'; 

CString str1=""; 

WCHAR str2[5]={0,0,0,0,0}; 

int j=0; 

do 

           str1=str.Left(str.Find('#',1)); 

           str=str.Mid(str.Find('#',1)); 

            WCHAR i=0; 

           sscanf(str1,"#%d",&i); 

            str2[j]=i; 

            j++; 

}while(str1!=""); 

_bstr_t str3=str2;