七、Windows下多字节编码和Unicode的转换
Windows提供了API函数,可以把Unicode字符数组转换为GB2312字符串。其中,Unicode数组在传入时候最后一个为0,也就是所谓的null termidated字符串。在函数内部得到要返回字节串的大小,请求空间,进行真正的转换操作,指针在外部使用后释放,或者在类中加如其他的操作来处理,比如析构函数中释放。返回值为写到字节串里数目。
int StringEncode::UnicodeToGB2312(char **dest, const WCHAR *src)
{
char* buffer;
int size = ::WideCharToMultiByte(CP_ACP, 0, src, -1, NULL, 0, NULL, NULL);
// null termidated wchar's buffer
buffer = new char[size];
int ret = ::WideCharToMultiByte(CP_ACP, NULL, src, -1, buffer, size + 1, NULL, NULL);
if (*dest != 0)
delete *dest;
*dest = buffer;
return ret;
}
注:其中见到有人在使用的时候,申请缓冲区空间时候是申请了(zise + 1)个来,最后一个字节写'\0',结束字符串。但是在我调试时候发现:系统给的size已经包含了一个写入'\0'的字节,而且最后得到的串中,'\0'是已经被系统API写入了。(也许我的实验有错误,有待验证)。把Unicode字符数组转换为UTF-8和UTF-7的方法类似,只要是WideCharToMultiByte函数的第一个表示代码页参数改为CP_UTF7(65000)和CP_UTF8(65001)。
同样道理,把多字节转换为Unicode字符数组,也有相应的函数。和上面的函数类似,可以通过先提供一个空缓冲区而先得到需要的大小,然后开辟空间得到最后的字符数组。但是考虑到效率,可以适当牺牲一些空间,提供一个足够大的字符数组,数组大小在极端的情况下(全是ASCII)是和字节数组大小一样的。
int StringEncode::Gb2312ToUnicode(WCHAR **dest, const char *src)
{
int length = strlen(src); // null terminated buffer
WCHAR *buffer = new WCHAR[length + 1]; // WCHAR means unsinged short, 2 bytes
// provide enough buffer size for Unicodes
int ret = ::MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, src, length, buffer, length);
buffer[ret] = 0;
if (*dest != 0)
delete *dest;
*dest = buffer;
return ret;
}
注:删除以前的缓冲区时候的操作,其实没有必要判断是不是为空,因为删除空指针是没有问题的,因为delete内部提供了这样的机制。
八、URL 解码
用IE发送GET请求的时候,URL是用UTF-8编码的,当对截包数据分析时候就需要对数据解码,下面的函数是一个简单的实现:
CString CTestUrlDlg::UrlToString(CString url)
{
CString str = "";
int n = url.GetLength();
url.MakeLower();
BYTE a, b1, b2;
for (int i=0; i= '0') && (c <= '9'))
d = c - '0';
else if ((c >= 'a') && (c <= 'f'))
{
d = c - 'a' + 10;
}
else if ((c >= 'A') && (c <= 'F'))
{
d = c - 'A' + 10;
}
else
d = 0;
return d;
}
static void UnicodeToGB2312(const WCHAR unicode, char* buffer)
{
// int size = ::WideCharToMultiByte(CP_ACP, 0, unicode, -1, NULL, 0, NULL, NULL);
int ret = ::WideCharToMultiByte(CP_ACP, NULL, &unicode, -1, buffer, 3, NULL, NULL);
}
CString CTestUrlDlg::Uft8ToGB(CString url)
{
CString str = "";
char buffer[3];
WCHAR unicode;
unsigned char * p = (unsigned char *)(LPCTSTR)url;
int n = url.GetLength();
int t = 0;
while (t < n)
{
unicode = UTF8ToUnicode(p, t);
UnicodeToGB2312(unicode, buffer);
buffer[2] = 0;
str += buffer;
}
return str;
}
示例:
CString str = "/MFC%E8%8B%B1%E6%96%87%E6%89%8B%E5%86%8C.chm";
CString ret = UrlToString(str);
ret = Uft8ToGB(ret); // MFC英文手册.chm
九、总结
常见算法还有MIME等,由于篇幅限制,并且网上已经有很多帖子,在此不再赘述。
对于本文,由于个人能力有限,难免有疏漏的地方,还望指教,共同进步。