ansi unicode,ansi编码转换unicode
最近在学习中总会遇到CString字符串转换成char*的问题。在这里,我将总结一下unicode项目下的字符串处理问题。
简述Ansi和Unicode及其各自的优缺点:
它们是两个字符的编码格式,Ansi=窄字节,Unicode=宽字节。Ansi用char格式表示一个字符,占用一个字节的存储空间,最多表示255个字符,表示英文还可以,但对于中文、日文、韩文等语言就不够用了。所以,如果你的程序是Ansi编码的,那么用中文写的程序在日文、韩文等系统上会出现乱码。所以用Unicode,用两个字节来表示一个字符,格式是无符号short,定义为wchar_t格式,这样就可以表示世界上大部分语言了!但是有利也有弊。劣势呢?也就是空间占用增加了一倍,网络传输的数据量也增加了(一倍)。
摘要:Windows 2000及以后的Xp、2003、Vista、Win7等系统都是使用Unicode从零开始开发的。如果调用任何Windows API函数并向其传递ANSI字符串,则系统将首先将该字符串转换为Unicode,然后将该Unicode字符串传递给操作系统。如果您希望函数返回ANSI字符串,系统将首先将Unicode字符串转换为ANSI字符串,然后将结果返回给您的应用程序。转换这些字符串需要时间和系统内存。Unicode通常用于避免系统转换所消耗的资源。
不同编码格式下的字符串处理和相互转换:
人们编程时经常遇到的数据类型:(以下对应的都是一样的)
Ansi:
char、char *、const char *
CHAR 、( PCHAR、PSTR、LPSTR)、LPCSTR
Unicode:
wchar_t、wchar_t *、const wchar_t *
WCHAR 、( PWCHAR、PWSTR、LPWSTR)、LPCWSTR
T通用型:
TCHAR 、( TCHAR *、PTCHAR、PTSTR、LPTSTR)、LPCTSTR
上图,其中:P代表指针,STR代表字符串,L代表长指针,在WIN32平台下可以忽略,C代表const常量,W代表wide wide byte,T代表template,表示通用。使用时,系统会根据当前工程性质进行转换。比如在unicode下,TCHAR实际上是wCHAR_t,否则就定义为char。
字符串类型对象的定义:
Ansi:char * pan istr= hello ;
Unicode:wchar _ t * pUnicodeStr= hello ;
通用型:TCHAR * pTStr=_ T( hello );或者TCHAR * pTStr=_ TEXT( hello );(_T,_TEXT也是这个意思)
动态应用内存:TCHAR *pszBuf=新TCHAR[100];
常用的字符串处理函数,详见MSDN:
字符串长度:
Ansi:strlen(char * str);
Unicode:wcs len(wchar _ t * str);
通用函数:_ TCS len(TCHAR * str);
Ansi:int atoi(const char * str);
Unicode:int _ wtoi(const wchar _ t * str);
通用函数:_tstoi(常量TCHAR * str);
字符串副本:
Ansi:strcpy(char * strDestination,const char * strSource);
Unicode:wcs cpy(wchar _ t * strDestination,const wchar _ t * strSource);
通用函数:_ tcscpy (tchar * strdestination,consttchar * strsource);
以上函数不安全,在vs2003及以上版本的编译器中会有警告提示。以下是安全函数(vc 6.0不支持):
Ansi:strcpy _ s(char * strDestination,size_t numberOfElements,const char * strSource);
Unicode:wcs cpy _ s(wchar _ t * strDestination,size_t numberOfElements,const wchar _ t * strSource);
通用函数:_ tcscpy _ s (tchar * strdestination,size _ t元素个数,consttchar * strsource);
元素数量
目标字符串缓冲区的大小。目标缓冲区的大小,单位是字节,不是字符!
Size_t无符号整数,MSDN解释:sizeof运算符的结果,也就是说size _ t是无符号整数,即无符号整数。那为什么会有size_t这种类型?
因为int/long等不同类型的操作系统(32/64)占用的字节数是不一样的,而size_t在不同的平台有不同的定义。有点像TCHAR类型:
#ifndef _SIZE_T_DEFINED
#ifdef _WIN64
typedef unsigned _ _ int 64 size _ t;//8个字节,64位
#否则
typedef _W64无符号int size _ t;//4个字节,32位
#endif
#定义大小T定义
#endif
ANSI和Unicode字符串类型之间的转换:
上面说的窄字节都是窄字节,宽字节都是宽字节,下面是它们之间的转换。
在程序中,仍然不建议您来回转换字符串编码,使用Ansi或Unicode。
但有些API函数往往只提供窄字节版本(如GetProcAddress,见MSDN)或宽字节版本(如CommandLineToArgvW,见MSDN)。
这时候就需要转换字符串编码格式了。
不过要提醒一下,并不是所有的都需要转换,有些是不需要的,比如socket中的send或者recv函数。
=================================================
字符串占用的字节数:
Ansi:
char sztr[]= ABC ;
占用字节数:sizeof(sztr);
char * psz= defgh
求占用字节数:strlen(PSZ)* sizeof(char);
Unicode:
wchar _ t szwStr[]=L ABC ;
占用字节数的计算:sizeof(szwStr);
wchar _ t * pwsz=L defgh
占用字节数:wcs len(pwsz)* sizeof(wchar _ t);
一般功能:
TCHAR sztr[]=_ T( ABC );
占用字节数:sizeof(sztr);
TCHAR * PSZ=_ T( defgh );
求占用字节数:_ TCS len(PSZ)* sizeof(TCHAR);
=======================================================
转换中使用的最基本的API函数:
WideCharToMultiByte实现宽字节到窄字节的转换。
MultiByteToWideChar将窄字节转换为宽字节。
T2W、W2A、T2A和T2W宏的使用和注意事项:
实际上,这些宏基本上都使用了上述两个函数。
[1],这些函数都在堆栈中分配空间。例如:A2W(abc ),将在堆栈中分配一块内存来存储 abc
[2]在使用上述宏之前,使用USES_CONVERSION宏。
*unicode下CString和char*之间的转换;
将CString转换为char*:使用wcstombs()函数
示例:
CString字符串;
Str=你好,你好;
char ch[50];
wcstombs(ch,str,siez of(ch));
这种转换会产生问题,因为str有汉字。如果在setlocale(LC_ALL,)包含中文字符之前使用了它,则应该包含头文件locale.h来设置默认语言。
Char*到CString:使用A2T()函数:
示例:
USES _ CONVERSION
char ch[5]= what ;
CString字符串;
str=A2T(ch);
更常用的调用方式可以百度知道。