您的位置:首页 > 数据库 > MySQL

vc6 mysql 编码方面的一些问题手记

2009-05-27 09:15 211 查看
最近在用VC6做信息抓取方面的一些工作,前两天初步研究了正则表达式,很方便的从网上把信息抓取下来了,后台存储用了Mysql数据库,主要也是为了以后Web开发方便。不过,Mysql在使用的过程中编码方面遇到了一些问题,这里记录下来,为自己也为可能遇到这方面问题的朋友提供参考。

中文网页编码现在主要是Gb2132和Utf8比较多,从网上抓取网页的时候,Gb2132在VC6里不用做转化,因为VC6默认的就是多字节存储,不会遇到乱码的问题,但如果网页是Utf8编码,则抓取的结果就是乱码,需要将utf8转到多字节以便在VC内处理。如可以按下面转化一下:

//////////////////////////

int n = MultiByteToWideChar(CP_UTF8,0,strData,strData.GetLength(),NULL,0);

WCHAR *pChar = new WCHAR[n+1];

MultiByteToWideChar(CP_UTF8,0, strData, strData.GetLength(),pChar,n);

pChar
= 0;

char szANSI[1024];

WideCharToMultiByte ( CP_ACP, WC_COMPOSITECHECK, pChar, -1, szANSI, sizeof(szANSI), NULL, NULL );

///////////////////////////

szANSI就是可以使用的多字节字符串了。

在对VC6内部对字符串处理完后,存储到Mysql数据库时也会遇到编码的问题。

需要说明的是,如果存储的时候不根据数据库的编码设置进行相应的编码处理,虽然数据能存入数据库,但取的时候就会出问题了,大部分情况下你会看到一对乱码,而不知道改如何处理。

所以,在这里我们设置数据库的存储编码格式为Utf8(主要是应用方便,也可以是别的,如Gb3132等),这样建立表的时候最好显式说明一下。

//////////////////////////

create table if not exists xxx(id int(4) not null primary key auto_increment, ...) default charset = utf8;

连接数据库时,在mysql_init(&g_mysql)之后,设置一下读写编码:

mysql_query( &g_mysql, _T("set names 'utf8'")

//////////////////////////

这样,准备工作做完了,存储的时候就是编码转换的问题了。因为VC6里字符串是多字节编码(其实应该就是gb2132),存储的时候Mysql数据库是Utf8编码,如果不转换,插入时就会出错,给出字符不能识别的错误提示。

在这里, 我们需要一个字符编码转换函数,参考http://www.vckbase.com/document/viewdoc/?id=1444里面的转换函数GB2312ToUTF_8:

//////////////////////////

//GB2312 转为 UTF-8

char* GB2312ToUTF_8(char *pText, int pLen)

{

int nULen = 1 + pLen*2;//pLen + (pLen >> 2) + 2;

char buf[4];

char* rst = new char[nULen];

memset(buf,0,4);

memset(rst,0,nULen);

int i = 0;

int j = 0;

while(i < pLen)

{

//如果是英文直接复制就可以

if( *(pText + i) >= 0)

{

rst[j++] = pText[i++];

}

else

{

WCHAR pbuffer;

Gb2312ToUnicode(&pbuffer,pText+i);

UnicodeToUTF_8(buf,&pbuffer);

unsigned short int tmp = 0;

tmp = rst[j] = buf[0];

tmp = rst[j+1] = buf[1];

tmp = rst[j+2] = buf[2];

j += 3;

i += 2;

}

}

rst[j] = '\0';

return rst;

}

注意原文中在字符串长度计算时有点小问题,上面改了一下,返回开辟内存的指针,用完后记得释放内存;

对了,用到的几个函数,如下:

// 把UTF-8转换成Unicode

void UTF_8ToUnicode(WCHAR* pOut,char *pText)

{

char* uchar = (char *)pOut;

uchar[1] = ((pText[0] & 0x0F) << 4) + ((pText[1] >> 2) & 0x0F);

uchar[0] = ((pText[1] & 0x03) << 6) + (pText[2] & 0x3F);

return;

}

// Unicode 转换成UTF-8

void UnicodeToUTF_8(char* pOut,WCHAR* pText)

{

// 注意 WCHAR高低字的顺序,低字节在前,高字节在后

char* pchar = (char *)pText;

pOut[0] = (0xE0 | ((pchar[1] & 0xF0) >> 4));

pOut[1] = (0x80 | ((pchar[1] & 0x0F) << 2)) + ((pchar[0] & 0xC0) >> 6);

pOut[2] = (0x80 | (pchar[0] & 0x3F));

return;

}

// 把Unicode 转换成 GB2312

void UnicodeToGB2312(char* pOut,unsigned short uData)

{

WideCharToMultiByte(CP_ACP,NULL,&uData,1,pOut,sizeof(WCHAR),NULL,NULL);

return;

}

// GB2312 转换成 Unicode

void Gb2312ToUnicode(WCHAR* pOut,char *gbBuffer)

{

::MultiByteToWideChar(CP_ACP,MB_PRECOMPOSED,gbBuffer,2,pOut,1);

return;

}

//////////////////////////

字符串经过上面的编码转换就可以存入到utf8编码的Mysql数据库了

strSQL.Format("insert into xxx(name, ...) values('%s', ...)", szName...);

if( mysql_query(&g_mysql, strSQL)!=0 )

{

cout<< mysql_error(&g_mysql) << endl;

errorFile.WriteString(strSQL);

continue;

}

delete[] szName;

/////////////////////////////////////////

不过上述代码在实际使用中我还遇到了一个问题,字符串中存在以下utf8字符时会导致SQL执行失败,

\xE0\x84\x81

\xE0\x82\xB7

\xE0\x80\xBF

\xE0\x90\x96

\xE0\x8B\x8A

初步想法是替换掉这些字符,如果有更好的办法,欢迎进一步交流探讨。

--------------------------------------------

ppzhang | giszhang@gmail.com | 2009-05-27
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: