平時Coding的時候,,經(jīng)常會遇到一些編碼轉(zhuǎn)換的問題,,尤其是UTF-8與ANSI 編碼轉(zhuǎn)換的問題。遇到好多回了,,所以不得不拿出來單獨看一下,。其實這個問題如果知道怎么做的話也不是問題,但是第一次接觸到的時候我卻是費了好大的功夫才搞出來,! 看一下下面的代碼
其中兩個主要的函數(shù)為: int MultiByteToWideChar(UINT CodePage, DWORD dwFlags, LPCSTR lpMultiByteStr, int cchMultiByte, LPWSTR lpWideCharStr, int cchWideChar); 函數(shù)功能:該函數(shù)映射一個字符串到一個寬字符(unicode)的字符串,。由該函數(shù)映射的字符串沒必要是多字節(jié)字符組。 int WideCharToMultiByte(UINT CodePage, DWORD dwFlags, LPWSTR lpWideCharStr, int cchWideChar, LPCSTR lpMultiByteStr, int cchMultiByte, LPCSTR lpDefaultChar, PBOOL pfUsedDefaultChar ); 函數(shù)功能:該函數(shù)映射一個unicode字符串到一個多字節(jié)字符串,。 具體參數(shù)百度百科講的很明白,,看一下就知道怎么回事了,我就不贅述了,。 其實就是這么點問題,,但是自己解決的時候卻費了很大的力氣,好處就是如果別的事情我可以我可以忘掉,,但是這個我真的再也忘不掉了,!
問題: sqlite 的編碼格式為ANSI Qt 默認的編碼格式為UTF-8 http://bbs.csdn.net/topics/360212350 Sqlite默認保存數(shù)據(jù)是用UTF8格式,而現(xiàn)有程序開發(fā)工具都是默認GB2312的格式,,所以你編程寫的中文不轉(zhuǎn)碼直接寫到庫里后,,用任何數(shù)據(jù)庫工具看肯定都是亂碼。但是讀出來之后仍然是GB2312,,所以顯示正常,。反之如果你用數(shù)據(jù)庫工具寫中文,,則默認存UTF8格式,用程序讀出來就是亂碼,。也就是你說的不可兼得,。 如果要實現(xiàn)能夠編程和數(shù)據(jù)庫工具讀寫都正常,必須要轉(zhuǎn)碼,。也就是說,保存時候,,要把GB2312轉(zhuǎn)成UTF8,,而讀出時候需要把UTF8在轉(zhuǎn)成GB2312。 網(wǎng)上有源程序可用,,叫做CCodingConv的類,,你搜一個源碼,在每次執(zhí)行SQL語句之前,,將其轉(zhuǎn)換一下即可,。將整個SQL語句進行轉(zhuǎn)換,E文的會保持不變,,而中文的會自動轉(zhuǎn)換成合適的編碼,,執(zhí)行即可實現(xiàn)要求。 有關(guān)unicode,,UTF-8及 ANSI等編碼轉(zhuǎn)換1. ANSI美國國家標準碼,,操作系統(tǒng)默認的編碼格式;但是不同國家有不同的文字,,由此各個國家制定了自己的國標碼,,如GB2312等。注意,,各個國家制定時還是按照ANSI準則進行的:即不屬于ASCII(0~127)的一個文字(符號)占兩個字節(jié),,屬于ASCII的占一個字節(jié)。這樣一來,,一個大字符串用不同國標碼,,解釋的結(jié)果就不同(但一點就是,屬于ASCII部分的字符解釋出來是相同的),。 ANSI是編碼,,GB2312等國標碼是符合ANSI標準的字符集。字符集與編碼是兩回事,。 2. 字符 字符是一個符號,,如:'#','◎'等,,存儲時根據(jù)不同的編碼標準可能占用1個或多個字節(jié)的空間,。不同編碼標準下,,字符占用空間大小不同,如Unicode編碼所有字符都是2個字節(jié),,utf-8編碼占用從1個到6個不等,。 3. 多字節(jié)字符串: 字符串在內(nèi)存中,如果“字符”是以ANSI編碼形式存放的,,則一個字符可能使用一個字節(jié)或多個字節(jié)來表示,,稱這個字符串為ANSI字符串或多字節(jié)字符串。 4. Unicode: 統(tǒng)一碼,,任何字符都占兩個字節(jié),。各個國家文字、符號統(tǒng)一編碼,。 VC++或其他編程工具對漢字或字符都采用操作系統(tǒng)的編碼標準,,一般都是ANSI標準。這就涉及往其它編碼轉(zhuǎn)化的問題,。 5. ANSI與Unicode 如果ANSI全部屬于ASCII(0~127),,則 mbstowcs, wcstombs 即可。因為Unicode對ASCII(0~127)的處理是“直接擴展ANSI”--由一個字節(jié)到兩個字節(jié),。 size_t mbstowcs( wchar_t *wcstr, const char *mbstr, size_t count ); size_t wcstombs( char *mbstr, const wchar_t *wcstr, size_t count );對于不屬于ASCII的,,如漢字,使用 WideCharToMultiByte,,MultiByteToWideChar,。 int MultiByteToWideChar( UINT CodePage, // code page DWORD dwFlags, // character-type options LPCSTR lpMultiByteStr, // string to map int cbMultiByte, // number of bytes in string LPWSTR lpWideCharStr, // wide-character buffer int cchWideChar // size of buffer ); 6. 多字節(jié)到寬字符(Unicode) 待轉(zhuǎn)換的字符并不一定是多字節(jié)字符串(ANSI字符串),uft-8編碼的也可以,。 CodePage:待轉(zhuǎn)換的代碼頁,,如CP_ACP(ANSI),utf-8,; dwFlags: 0; lpMultiByteStr,,cbMultiByte:待轉(zhuǎn)換 lpWideCharStr,cchWideChar:轉(zhuǎn)換完 int WideCharToMultiByte( UINT CodePage, // code page DWORD dwFlags, // performance and mapping flags LPCWSTR lpWideCharStr, // wide-character string int cchWideChar, // number of chars in string LPSTR lpMultiByteStr, // buffer for new string int cbMultiByte, // size of buffer LPCSTR lpDefaultChar, // default for unmappable chars LPBOOL lpUsedDefaultChar // set when default char used ); 7. 寬字符(Unicode)到多字節(jié) 新字符串不必是多字節(jié)(ANSI)字符集,。 CodePag:要轉(zhuǎn)換成的代碼頁,,如CP_ACP(ANSI),utf-8,; dwFlags:0,; lpWideCharStr,cchWideChar:待轉(zhuǎn)換 lpMultiByteStr,,cbMultiByte:轉(zhuǎn)換完 lpDefaultChar,,lpUsedDefaultChar:失敗時缺省字符; 一個字符串中有utf-8,,如何轉(zhuǎn)換成ANSI,? 首先,,utf-8 到 Unicode 其次,Unicode 到 ANSI 代碼如下: int ConvUtf8ToAnsi(CString& strSource, CString& strChAnsi) { if (strSource.GetLength() <= 0) return 0; CString strWChUnicode; strSource.TrimLeft(); strSource.TrimRight(); strChAnsi.Empty(); int iLenByWChNeed = MultiByteToWideChar(CP_UTF8, 0, strSource.GetBuffer(0), strSource.GetLength(), NULL, 0); int iLenByWchDone = MultiByteToWideChar(CP_UTF8, 0, strSource.GetBuffer(0), strSource.GetLength(), (LPWSTR)strWChUnicode.GetBuffer(iLenByWChNeed * 2), iLenByWChNeed); strWChUnicode.ReleaseBuffer(iLenByWchDone * 2); int iLenByChNeed = WideCharToMultiByte(CP_ACP, 0, (LPCWSTR)strWChUnicode.GetBuffer(0), iLenByWchDone, NULL, 0, NULL, NULL); int iLenByChDone = WideCharToMultiByte(CP_ACP, 0, (LPCWSTR)strWChUnicode.GetBuffer(0), iLenByWchDone, strChAnsi.GetBuffer(iLenByChNeed), iLenByChNeed, NULL, NULL); strChAnsi.ReleaseBuffer(iLenByChDone); if (iLenByWChNeed != iLenByWchDone || iLenByChNeed != iLenByChDone) return 1; return 0; } 8. Unicode 到 ANSI 其它方法 1. 調(diào)用CRT 函數(shù)wcstombs(),; 2. 使用CString 構(gòu)造器或賦值操作(僅用于MFC ),; 3. 使用ATL 串轉(zhuǎn)換宏; size_t wcstombs ( char* mbstr, // 接受結(jié)果ANSI串的字符(char)緩沖,。 const wchar_t* wcstr, // 要轉(zhuǎn)換的Unicode串,。 size_t count ); // mbstr參數(shù)所指的緩沖大小。 MFC中的CString包含有構(gòu)造函數(shù)和接受Unicode串的賦值操作,,所以你可以用CString來實現(xiàn)轉(zhuǎn)換,。 // 假設(shè)有一個Unicode串wszSomeString... CString str1 ( wszSomeString ); // 用構(gòu)造器轉(zhuǎn)換 CString str2; str2 = wszSomeString; // 用賦值操作轉(zhuǎn)換 ATL有一組很方便的宏用于串的轉(zhuǎn)換。W2A()用于將Unicode串轉(zhuǎn)換為ANSI串(記憶方法是“wide to ANSI”——寬字符到ANSI),。實際上使用OLE2A()更精確,“OLE”表示的意思是COM串或者OLE串,。 9. VC6 IDE下查看Unicode字符的方法 unicode字符后面加",su" |
|