遇到这样一个问题,程序使用的是Unicode编码,从Edit中读取出来的Cstring内容直接存储到txt文件中会出现乱码。
txt使用的ANSI编码,而Edit空间中的内容是Unicode编码,所以会出现乱码。
百度一下才知道,编译器的库函数中存在Unicode与ANSI之间相互转化的函数。
1. ANSI转化为Unicode
MultiByteToWideChar 这个函数将ANSI转化为Unicode
原函数:
int MultiByteToWideChar(
UINT CodePage,
DWORD dwFlags,
LPCSTR lpMultiByteStr,
int cchMultiByte,
LPWSTR lpWideCharStr,
int cchWideChar
);
参数说明:
CodePage参数标识了与多字节字符串关联的一个代码页值。我自己理解就是要转化成的字符串的编码方式。
dwFlags参数允许我们进行额外的控制,它会影响带变音符号(比如重音)的字符,但是,一般情况下不使用这个标识,所以传给dwFlags的值是0。
lpMultiByteStr参数指定要转换的字符串。
cchMultiByte参数指定字符串的长度(字节数)。如果传给cchMultiByte的参数值是-1,函数便可自动判断源字符串的长度。
lpWideCharStr参数指定的是一个内存缓冲区的地址,缓冲区的内容是转换后的Unicode版本的字符串。
cchWideChar参数指定缓冲区的最大长度(字符数)
一般按照以下步骤将一个多字节字符串转化为Unicode形式
(1)调用MultiByteToWideChar,为lpWideCharStr参数传入NULL,为cchWideChar参数传入0,为cchMultiByte参数传入-1。
(2)分配一块足以容纳转换后的unicode字符串的内存。它的大小是上一个MultiByteToWideChar调用的返回值乘以sizeof(wchar_t)
(3)再次调用MultiByteToWideChar,这一次将缓冲区作为lpWideCharStr参数的传入值,将第一次MultiByteToWideChar调用的返回值乘以sizeof(wchar_t)得到的大小作为cchWideChar参数的传入值。
(4)使用转换后的字符串。
(5)释放Unicode字符串占用的内存。
下面是一个简单的例子:
LPCSTR strMulti = "鎯呭喌?";
int iNum = MultiByteToWideChar(CP_UTF8, 0, strMulti, -1, NULL, 0);
LPWSTR pUniCode = new WCHAR[sizeof(wchar_t) * iNum];
MultiByteToWideChar(CP_UTF8, 0, strMulti, -1, pUniCode, sizeof(wchar_t) * iNum );
delete []pUniCode;
最后pUniCode的结果是UTF8编码的“情况?”
2. Unicode转化为ANSI
WideCharToMultiByte 这个函数将Unicode转化为ANSI
函数原型:
int WideCharToMultiByte(
UINT CodePage,
DWORD dwFlags,
LPCWSTR lpWideCharStr,
int cchWideChar,
LPSTR lpMultiByteStr,
int cchMultiByte,
LPCSTR lpDefaultChar,
LPBOOL pfUsedDefaultChar //至少有一个字符不能转换为其多字节形式,函数就会把这个变量设为TRUE
);
参数说明:
CodePage参数标识了要与新转换的字符串关联的代码页,代码页包含如下几个值:
dwFlags参数允许我们指定额外的转化控制,这些标志会影响带变音符号的字符和系统不能转换的字符。但是我们一般不需要这种转换,所以传入参数设置为0
lpWideCharStr参数指定要转换字符串的内存地址。
cchWideChar参数指出该字符串的长度(字符数),如果此参数传入-1,由函数来判断字符串的长度。
lpMultiByteStr参数指向转换后字符串的缓存区地址。
cchMultiByte参数中指定此缓存的最大值(字节数)。如果将其设置为0,将会返回目标缓存区需要的大小。
这个函数与上面函数的主要区别是,无需在进行乘法运算,它返回的目标缓存区的大小就是所需的字节数。
注意:此函数比上面的函数参数要多两个,分别是lpDefaultChar、pfUsedDefaultChar。只有一个字符在uCodePage指定的代码页中没有对应的表示时,WideCharToMultiByte函数才会使用这两个参数,在遇到一个不能转换的宽字符时,函数便使用lpDefaultChar参数指向的字符。如果这两个参数为NULL,函数会使用系统默认的字符。这个默认字符通常是一个问号。这对文件名来说非常危险,因为问号是一个通配符。pfUsedDefaultChar参数指向一个布尔变量,在宽字符字符串中,如果至少有一个字符不能转换为对应的多字节形式,函数就会把这个变量设置为TRUE,如果所有字符都能成功转化,就会把这个变量设置为FALSE,我们可以在函数返回后测试该变量,验证宽字符串是否已经转化成功,同样,我们可以通过此参数传入NULL值。
DWORD dwNum = WideCharToMultiByte(CP_ACP,NULL,strText,-1,NULL,0,NULL,FALSE);
char *psText;
psText = new char[dwNum];
WideCharToMultiByte (CP_ACP, NULL, strText,-1, psText,dwNum,NULL,FALSE);
delete []psText;