您的位置:首页 > 其它

unicode 和 mbcs、ansi 转换

2013-10-01 18:49 465 查看
1: 首先更改项目属性为多字节字符集.

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

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

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

3: 替换所有的 WCHAR 为 TCHAR

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

ps1: 最好使用那些能够根据编译条件自动替换的函数.

想所有的windowsAPI, 他都提供了两个版本. 可以根据编译条件自动替换

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(这个0x00是ANSI的一个字符, MSCB肯定兼容了)

对于 char * pStr = "ddd中";

ANSI函数 strlen: 返回 5

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

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

UNICODE 想ansi转化的c函数:

char sChar[MAX_PATH];

const WCHAR wChar[] = L"我的朋友";

// 把wChar这个Unicode字符串转换成ANSI字符串,保存到sChar,并且返回ANSI的字符串大小,如果失败,则返回-1

wcstombs(sChar, wChar, MAX_PATH);

这样是运行不过不去的,总是返回-1。

后来经人提醒,需要在调用wcstombs之前要先设置代码页:

char sChar[MAX_PATH];

const WCHAR wChar[] = L"我的朋友";

// 设置代码页为默认代码页

_tsetlocale(LC_ALL,_T(""));

// 把wChar这个Unicode字符串转换成ANSI字符串,保存到sChar,并且返回ANSI的字符串大小,如果失败,则返回-1

wcstombs(sChar, wChar, MAX_PATH);

这样就可以了!不用调用烦人的WideCharToMultiByte!多好啊!

相反的函数:mbstowcs,可以从ANSI转换到Unicode

具体参考:

http://www.cppblog.com/mybios/archive/2006/11/30/15817.html

有关UNICODE、ANSI字符集和相关字符串操作的总结!

http://hi.baidu.com/flyownway/blog/item/c284bedd664ec3da8d1029d6.html

error C2440: '=' : cannot convert from 'const char [23]' to 'LPCWSTR'

查了好多资料最终才意识到原来是UNICODE字符集的问题,现在找来资料看看,希望能帮助像我一样的菜鸟。

Q UNICODE字符串如何显示

A

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

WCHAR *str=L"unicodestring";

TextOut(0,0,str);

否则就需要转换类型

#include <comdef.h>

WCHAR *str=L"unicodestring";

bstr_t str1=str;

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

Q 如何实现ANSI和UNICODE的相互转换

A

将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);

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

因 为ANSI转UNICODE,如果使用A2W或MultiByteToWideChar(第一个参数是CP_ACP)的话,是根据系统默认的转码表,把转 入的ANSI字符串看作Multi-Bytes字符串处理的,如果是中文(中文windows默认就是中文),一个大于0x87的byte可能和下一 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~0x87的ANSI字符串,对应的Unicode码就是相同的16位值,至于其他的,你的字符串反正加了密,没必要转 换成显示出来是一样的字符,就按同样的方法处理了,其实如果中间的字符串不用显示或别的,直接reutrn (LPWSTR)lpANSI;过去也可以, 反正接受的时候自己清楚就可以了。

Q 如何让程序支持UNICODE

A

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

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

(0).1.改语言定义:

在project settings的"C++"页中的"preprocessor definitions"中改_MBCS为_UNICODE

(0).2.改入口函数:

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

(1)在代码上,处理字符中的多用TCHAR.H中的宏,如strcpy用_tcscpy代替,用TCHAR代char,

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

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

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

A

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

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

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

A

函数 描述

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

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

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

Q 为什么要使用Unicode?

A

(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公司将COM从16位Windows转换成Win32时,公司决定需要字符串的所有COM接口方法都只能接受Unicode字符串。

Q 如何编写Unicode源代码?

A

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

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

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

A

数据类型 说明

WCHAR Unicode字符

PWSTR 指向Unicode字符串的指针

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

对应的ANSI数据类型为CHAR,LPSTR和LPCSTR。

ANSI/Unicode通用数据类型为TCHAR,PTSTR,LPCTSTR。

Q 如何对Unicode进行操作?

A

字符集 特性 实例

ANSI 操作函数以str开头 strcpy

Unicode 操作函数以wcs开头 wcscpy

MBCS 操作函数以_mbs开头 _mbscpy

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

ANSI/Unicode 操作函数以lstr开头 lstrcpy(Windows函数)

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

#ifdef UNICODE

#define CreateWindowEx CreateWindowExW

#else

#define CreateWindowEx CreateWindowExA

#endif // !UNICODE

Q 如何表示Unicode字符串常量?

A

字符集 实例

ANSI “string”

Unicode L“string”

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

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

A

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

如:StrCat,StrChr,StrCmp和StrCpy等。

Q 如何编写符合ANSI和Unicode的应用程序?

A

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

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

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

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

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

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

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

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

A

通过调用CompareString来实现。

标志 含义

NORM_IGNORECASE 忽略字母的大小写

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

NORM_IGNORENONSPACE 忽略无间隔字符

NORM_IGNORESYMBOLS 忽略符号

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

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

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

A

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

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

A

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

Q 如何在Unicode与ANSI之间转换字符串?

A

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

Q 如何得到汉字的Unicode编码

A

#include "comdef.h"

char *str1="你好";

_bstr_t str=str1;

WCHAR *str2=str;

str2就是你要的UNICODE码

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

A

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;
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: