来自 :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的编码还不是很熟悉,呵呵,等以后有空的时候再去了解一下编码吧。