1、Windows版本下的UTF-8编码的转换:
项目组以前实现了对MD5签名的初期版本,但是无法支持汉字等宽字符的转换。以前对于所有的char*型字符,直接一个byte*型,强制转换成byte型字符。但是这么做有很大的弊端,256个ASCII字符本身只有一个字节,所有强制将char*字符转换成byte*型字符没有问题,可是对于汉字等宽字符,由于每个字符有2个字节的宽度,所以转换之后,将会出现乱码。
而如果将char*型字符转换成UTF-8编码,将不会出现上述问题。
UTF-8对于ASCII字符仍保持原值,而对于非ASCII字符则进行了转换。具体知识可以查看相关的UTF-8编码知识。
windows下GB2312转UTF-8
具体实现:
char* Gb2312ToUTF_8(char* gb2312)
实现将GB2312编码转换成UTF-8编码。
其中调用了windows.h中的系统函数
以下是MSDN中对我调用的系统函数的解释
Maps a character string to a wide character (Unicode UTF-16) string. The character string mapped by this function is not necessarily from a multibyte character set.
int MultiByteToWideChar(
UINT CodePage,
DWORD dwFlags,
LPCSTR lpMultiByteStr,
int cbMultiByte,
LPWSTR lpWideCharStr,
int cchWideChar
);
Maps a wide character string to a new character string. The new character string is not necessarily from a multibyte character set.
int WideCharToMultiByte(
UINT CodePage,
DWORD dwFlags,
LPCWSTR lpWideCharStr,
int cchWideChar,
LPSTR lpMultiByteStr,
int cbMultiByte,
LPCSTR lpDefaultChar,
LPBOOL lpUsedDefaultChar
);
源代码:
char* Gb2312ToUTF_8(char* gb2312)
{
int len = MultiByteToWideChar(CP_ACP, 0, gb2312, -1, NULL, 0);
wchar_t* wstr = new wchar_t[len+1];
memset(wstr, 0, len+1);
MultiByteToWideChar(CP_ACP, 0, gb2312, -1, wstr, len);
len = WideCharToMultiByte(CP_UTF8, 0, wstr, -1, NULL, 0, NULL, NULL);
char* str = new char[len+1];
memset(str, 0, len+1);
WideCharToMultiByte(CP_UTF8, 0, wstr, -1, str, len, NULL, NULL);
if(wstr) delete[] wstr;
return str; // _DEBUG
}
上面得到还是char*型表示的UTF-8编码,为了适应MD5,我编写了一个转换函数实现char*转byte*
//char转byte型。
int MD5::charToByte(char *SrcData,int len)
{
char* destPtr = SrcData;
BUtf8 = new byte[len];
for(int i=0; i<len; i++)
{
if(*destPtr < 0)
BUtf8[i] = 256 + *destPtr;
else
BUtf8[i] = *destPtr;
destPtr++;
}
return len;
}
此处要注意释放BUtf8指针,我的实现是在MD5的析构函数中释放。
经过测试后,一切正常。
可怜的5.4居然还要加班。。
我以为实现了UTF-8编码转换功能,谁知道还有Linux版本的UTF-8忘了实现。Windows版本是调用了windows的系统函数,而linux却不能调用这个函数。
于是,马上找资料。
2、Linux版本下UTF-8转换
char* Gb2312ToUTF_8(char* gb2312)
涉及到得头文件及函数:
#include <iconv.h>
具体实现
int MD5::code_convert(char *from_charset,char *to_charset,char *inbuf,int inlen,char *outbuf,int outlen)
{
#ifndef WIN32
iconv_t cd;
int rc;
char **pin = &inbuf;
char **pout = &outbuf;
cd = iconv_open(to_charset,from_charset);
if (cd==0) return -1;
memset(outbuf,0,outlen);
if (iconv(cd,pin,(size_t*)&inlen,pout,(size_t*)&outlen)==-1) return -1;
iconv_close(cd);
#endif
return 0;
}