vc6 mysql 編碼方面的一些問題手記

來源:互聯網
上載者:User

最近在用VC6做資訊抓取方面的一些工作,前兩天初步研究了Regex,很方便的從網上把資訊抓取下來了,後台儲存用了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[n] = 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

 

 

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.