来自 :http://www.diybl.com/course/3_program/c++/cppsl/2008320/105871.html
GBK和UTF8之间的转换可以使用MultiByteToWideChar和WideCharToMultiByte两个API,方法是先把它们转换为中间编码Unicode,再转换为对应的编码即可。
#include < stdio.h >
#include < windows.h >
// GBK编码转换到UTF8编码
int GBKToUTF8(unsigned char * lpGBKStr,unsigned char * lpUTF8Str, int nUTF8StrLen)
{
wchar_t * lpUnicodeStr = NULL;
int nRetLen = 0 ;
if ( ! lpGBKStr) // 如果GBK字符串为NULL则出错退出
return 0 ;
nRetLen = ::MultiByteToWideChar(CP_ACP, 0 ,( char * )lpGBKStr, - 1 ,NULL,NULL); // 获取转换到Unicode编码后所需要的字符空间长度
lpUnicodeStr = new WCHAR[nRetLen + 1 ]; // 为Unicode字符串空间
nRetLen = ::MultiByteToWideChar(CP_ACP, 0 ,( char * )lpGBKStr, - 1 ,lpUnicodeStr,nRetLen); // 转换到Unicode编码
if ( ! nRetLen) // 转换失败则出错退出
return 0 ;
nRetLen = ::WideCharToMultiByte(CP_UTF8, 0 ,lpUnicodeStr, - 1 ,NULL, 0 ,NULL,NULL); // 获取转换到UTF8编码后所需要的字符空间长度
if ( ! lpUTF8Str) // 输出缓冲区为空则返回转换后需要的空间大小
{
if (lpUnicodeStr)
delete []lpUnicodeStr;
return nRetLen;
}
if (nUTF8StrLen < nRetLen) // 如果输出缓冲区长度不够则退出
{
if (lpUnicodeStr)
delete []lpUnicodeStr;
return 0 ;
}
nRetLen = ::WideCharToMultiByte(CP_UTF8, 0 ,lpUnicodeStr, - 1 ,( char * )lpUTF8Str,nUTF8StrLen,NULL,NULL); // 转换到UTF8编码
if (lpUnicodeStr)
delete []lpUnicodeStr;
return nRetLen;
}
// UTF8编码转换到GBK编码
int UTF8ToGBK(unsigned char * lpUTF8Str,unsigned char * lpGBKStr, int nGBKStrLen)
{
wchar_t * lpUnicodeStr = NULL;
int nRetLen = 0 ;
if ( ! lpUTF8Str) // 如果UTF8字符串为NULL则出错退出
return 0 ;
nRetLen = ::MultiByteToWideChar(CP_UTF8, 0 ,( char * )lpUTF8Str, - 1 ,NULL,NULL); // 获取转换到Unicode编码后所需要的字符空间长度
lpUnicodeStr = new WCHAR[nRetLen + 1 ]; // 为Unicode字符串空间
nRetLen = ::MultiByteToWideChar(CP_UTF8, 0 ,( char * )lpUTF8Str, - 1 ,lpUnicodeStr,nRetLen); // 转换到Unicode编码
if ( ! nRetLen) // 转换失败则出错退出
return 0 ;
nRetLen = ::WideCharToMultiByte(CP_ACP, 0 ,lpUnicodeStr, - 1 ,NULL,NULL,NULL,NULL); // 获取转换到GBK编码后所需要的字符空间长度
if ( ! lpGBKStr) // 输出缓冲区为空则返回转换后需要的空间大小
{
if (lpUnicodeStr)
delete []lpUnicodeStr;
return nRetLen;
}
if (nGBKStrLen < nRetLen) // 如果输出缓冲区长度不够则退出
{
if (lpUnicodeStr)
delete []lpUnicodeStr;
return 0 ;
}
nRetLen = ::WideCharToMultiByte(CP_ACP, 0 ,lpUnicodeStr, - 1 ,( char * )lpGBKStr,nRetLen,NULL,NULL); // 转换到GBK编码
if (lpUnicodeStr)
delete []lpUnicodeStr;
return nRetLen;
}
// 使用这两个函数的例子
int main()
{
char cGBKStr[] = " 我是中国人! " ;
char * lpGBKStr = NULL;
char * lpUTF8Str = NULL;
FILE * fp = NULL;
int nRetLen = 0 ;
nRetLen = GBKToUTF8((unsigned char * )cGBKStr,NULL,NULL);
printf( " 转换后的字符串需要的空间长度为:%d " ,nRetLen);
lpUTF8Str = new char [nRetLen + 1 ];
nRetLen = GBKToUTF8((unsigned char * )cGBKStr,(unsigned char * )lpUTF8Str,nRetLen);
if (nRetLen)
{
printf( " GBKToUTF8转换成功! " );
}
else
{
printf( " GBKToUTF8转换失败! " );
goto Ret0;
}
fp = fopen( " C:\GBK转UTF8.txt " , " wb " ); // 保存到文本文件
fwrite(lpUTF8Str,nRetLen, 1 ,fp);
fclose(fp);
getchar(); // 先去打开那个文本文件看看,单击记事本的“文件”-“另存为”菜单,在对话框中看到编码框变为了“UTF-8”说明转换成功了
nRetLen = UTF8ToGBK((unsigned char * )lpUTF8Str,NULL,NULL); // 再转回来
printf( " 转换后的字符串需要的空间长度为:%d " ,nRetLen);
lpGBKStr = new char [nRetLen + 1 ];
nRetLen = UTF8ToGBK((unsigned char * )lpUTF8Str,(unsigned char * )lpGBKStr,nRetLen);
if (nRetLen)
{
printf( " UTF8ToGBK转换成功! " );
}
else
{
printf( " UTF8ToGBK转换失败! " );
goto Ret0;
}
fp = fopen( " C:\UTF8转GBK.txt " , " wb " ); // 保存到文本文件
fwrite(lpGBKStr,nRetLen, 1 ,fp);
fclose(fp);
getchar(); // 再去打开文本文件看看,发现编码框又变为了“ANSI”说明转换成功了
Ret0:
if (lpGBKStr)
delete []lpGBKStr;
if (lpUTF8Str)
delete []lpUTF8Str;
return 0 ;
}
在网上看到的一些文章说,UTF8转换为GBK的时候会有问题,特别是当UTF8字符串中的汉字数为奇数时。关于这个问题我没有去验证过,而且我对UTF8和GB2312的编码还不是很熟悉,呵呵,等以后有空的时候再去了解一下编码吧。