//主要思想:先将一种编码用MultiByteToWideChar函数变为Unicode编码,再用WideCharToMultiByte函数变为另一种编码。
/*********************************
MultiByteToWideChar
一、函数功能:该函数映射一个字符串到一个unicode字符串。
二、函数原型:int MultiByteToWideChar(UINT CodePage, DWORD dwFlags, LPCSTR lpMultiByteStr, int cchMultiByte, LPWSTR lpWideCharStr, int cchWideChar);
三、参数说明:
1.CodePage:指定执行转换的编码。常用的有CP_ACP:ANSI(gb*)、CP_UTF8:UTF-8
2.dwFlags:一组位标记用以指出是否未转换成预作或宽字符(若组合形式存在),是否使用象形文字替代控制字符,以及如何处理无效字符。
3.lpMultiByteStr:指向将被转换字符串的字符。
4.cchMultiByte:指定由参数lpMultiByteStr指向的字符串中字节的个数。如果这个值为-1,字符串将被设定为以NULL为结束符的字符串,并且自动计算长度。
5.lpWideCharStr:指向接收被转换字符串的缓冲区。
6.cchWideChar:指定由参数lpWideCharStr指向的缓冲区的字节个数。若此值为零,函数返回缓冲区所必需的宽字符数,在这种情况下,lpWideCharStr中的缓冲区不被使用。
四、返回值:
1.如果函数运行成功,并且cchWideChar不为零,返回值是由lpWideCharStr指向的缓冲区中写入的宽字符数;
2.如果函数运行成功,并且cchMultiByte为零,返回值是接收到待转换字符串的缓冲区所需求的宽字符数大小。
3.如果函数运行失败,返回值为零。
五、注意: 指针lpMultiByteStr和lpWideCharStr必须不一样。
*****************************************/
/************************************
WideCharToMultiByte
一、函数功能:该函数映射一个unicode字符串到一个多字节字符串。
二、函数原型:int WideCharToMultiByte(UINT CodePage, DWORD dwFlags, LPWSTR lpWideCharStr, int cchWideChar, LPCSTR lpMultiByteStr, int cchMultiByte, LPCSTR lpDefaultChar, PBOOL pfUsedDefaultChar );
三、参数说明:
1.CodePage:指定执行转换的编码。
2.dwFlags:一组位标记用以指出是否未转换成预作或宽字符(若组合形式存在),是否使用象形文字替代控制字符,以及如何处理无效字符。
3.lpWideCharStr:指向将被转换的unicode字符串。
4.cchWideChar:指定由参数lpWideCharStr指向的缓冲区的字符个数。
5.lpMultiByteStr:指向接收被转换字符串的缓冲区。
6.cchMultiByte:指定由参数lpMultiByteStr指向的缓冲区最大值(用字节来计量)。
7.lpDefaultChar:通常设为NULL。
8.pfUsedDefaultChar:通常设为NULL。
四、返回值:
1.如果函数运行成功,并且cchMultiByte不为零,返回值是由 lpMultiByteStr指向的缓冲区中写入的字节数;
2.如果函数运行成功,并且cchMultiByte为零,返回值是接收到待转换字符串的缓冲区所必需的字节数。
3.如果函数运行失败,返回值为零。
*****************************************/
#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;
}
以下是linux下的代码,从big5到utf8的例子
#include <unistd.h>
#include <stdio.h>
#include <sys/types.h>
#include <iconv.h>
#include <sys/stat.h>
#include <fcntl.h>
#define SIZE 1024*1024
int Transcoding(char *fromcode,char *tocode,char *from,int from_len,char *to,int to_len)
{
iconv_t cd;
//form big5 to utf-8
cd = iconv_open(tocode,fromcode);
/*size_t iconv(iconv_t cd,char **inbuf,size_t *inbytesleft,char **outbuf,size_t *outbytesleft);
此函数从inbuf中读取字符,转换后输出到outbuf中,inbytesleft用以记录还未转换的字符数,outbytesleft用以记录输出缓冲的剩余空间。
*/
if( iconv(cd,&from,&from_len,&to,&to_len) == -1 )
printf("转换矢败!\n");
else
printf("转换成功!\n");
iconv_close(cd);
return SIZE-to_len;
}
//./test big5 utf-8 big5.txt utf8.txt
int main(int argc,char **argv[])
{
char buf[SIZE];
char result[SIZE];
int fd_read,fd_write,n,m;
fd_read = open(argv[3],O_RDONLY);
fd_write = open(argv[4],O_WRONLY|O_CREAT);
if(fd_read < 0)
printf("不能打开源文件!\n");
if(fd_write < 0)
printf("不能打开目标文件!\n");
n=read(fd_read,buf,SIZE);
m=Transcoding(argv[1],argv[2],buf,n,result,SIZE);
write(fd_write,result,m);
fclose(fd_read);
fclose(fd_write);
return 0;
}