曾經碰到乙個問題,
專案需要支援日文作業系統,但是沒有編譯成unicode程式。
然後在乙個解析使用者輸入路徑的地方出問題了。
原因是日文的"表"這個漢字,日文編碼格式下,低位元組和反斜槓'/'編碼一樣,解析的時候把它當成路徑的分隔符了。:-(
// 項: 8d 80 (shift_jis)
// 目: 96 da (shift_jis)
// 表: 95 5c (shift_jis)
// /: 5c (shift_jis)
反思一下,如果要支援國際化,最正確也最簡單的辦法是都編譯成unicode程式。
當然這樣就很有可能需要進行些字符集的轉換,整理了4個函式。
還可以組合使用,比如要多位元組字串-->utf8格式字串,可以呼叫1)+3)。
1)當前系統編碼的多位元組字串-->unicode格式字串
bool multitounicode(const std::string& multitext, std::wstring& unicodetext) //先獲取轉換後字串所需空間 int size = ::multibytetowidechar(cp_acp, 0, multitext.c_str(), -1, null, 0); if (0 == size) //分配空間,進行轉換 wchar_t* wszbuffer = new wchar_t[size + 1]; ::zeromemory(wszbuffer, (size + 1) * sizeof(wchar_t)); if (0 == ::multibytetowidechar(cp_acp, 0, multitext.c_str(), -1, wszbuffer, size + 1)) unicodetext = wszbuffer; delete wszbuffer; return true; }
2)unicode格式字串-->當前系統編碼的多位元組字串
bool unicodetomulti(const std::wstring& unicodetext, std::string& multitext) //先獲取轉換後字串所需空間 int size = ::widechartomultibyte(cp_acp, 0, unicodetext.c_str(), -1, null, 0, null, null); if (0 == size) //分配空間,進行轉換 char* szbuffer = new char[size + 1]; ::zeromemory(szbuffer, (size + 1) * sizeof(char)); if (0 == ::widechartomultibyte(cp_acp, 0, unicodetext.c_str(), -1, szbuffer, size + 1, null, null)) multitext = szbuffer; delete szbuffer; return true; }
3)unicode格式字串-->utf8格式字串
bool unicodetoutf8(const std::wstring& unicodetext, std::string& utf8text) //先獲取轉換後字串所需空間 int size = ::widechartomultibyte(cp_utf8, 0, unicodetext.c_str(), -1, null, 0, null, null); if (0 == size) //分配空間,進行轉換 char* szbuffer = new char[size + 1]; ::zeromemory(szbuffer, (size + 1) * sizeof(char)); if (0 == ::widechartomultibyte(cp_utf8, 0, unicodetext.c_str(), -1, szbuffer, size + 1, null, null)) utf8text = szbuffer; delete szbuffer; return true; }
4)utf8格式字串-->unicode格式字串
bool utf8tounicode(const std::string& utf8text, std::wstring& unicodetext) //先獲取轉換後字串所需空間 int size = ::multibytetowidechar(cp_utf8, 0, utf8text.c_str(), -1, null, 0); if (0 == size) //分配空間,進行轉換 wchar_t* wszbuffer = new wchar_t[size + 1]; ::zeromemory(wszbuffer, (size + 1) * sizeof(wchar_t)); if (0 == ::multibytetowidechar(cp_utf8, 0, utf8text.c_str(), -1, wszbuffer, size + 1)) unicodetext = wszbuffer; delete wszbuffer; return true; }
補充1)
_unicode vs unicode
在學習unicode的過程中發現有兩種關於unicode的巨集定義: unicode和_unicode.
unicode:
這個巨集主要是在windows skd中使用, 比如getwindowtext(), 定義了unicode以後將被定義為getwindowtextw(unicode版本),否則被定義成getwindowtexta(ansi版本).
_unicode:
該巨集一般用在c執行時庫和mfc標頭檔案中, 這時候函式_tcslen()將被對映為wcslen(), 反之被對映為strlen(). 至於在mfc中, 一般存在如下的定義:
#ifdef _unicode
#ifndef unicode
#define unicode
#endif
#endif
#ifdef unicode
#ifndef _unicode
#define _unicode
#endif
#endif
所以在mfc使用哪個都可以.
總結:兩個都用上總不會有錯的:)
補充2)
vc6中為了編譯unicode軟體出了需要新增_unicode巨集定義外,還需要增加一步:指定程式的入口位置。
否則程式將會發生如下錯誤:error lnk2001: unresolved external symbol _winmain@16。
解決辦法:在project settings > entry-point symbol編輯框中輸入wwinmaincrtstartup。
補充3)
c++比unicode出生得早,所以最開始沒有考慮unicode支援,char型別是單位元組的。
wchar_t實際上是typedef定義。
所以特別要注意防止下面錯誤。
cstring stext = _t("123456789");
int nlength = stext.getlength() //i=9
cfile cfile;
......
cfile.write(stext,stext.getlength());
這段**再普通不過了,編譯也不會有任何問題。但是實際上輸出的內容將會是錯誤的。正確的**應該如下:
cstring stext = _t("123456789");
int nlength = stext.getlength() //i=9
cfile cfile;
......
cfile.write(stext,stext.getlength()×sizeof(_tchar));
Unicode以及字符集轉換
曾經碰到乙個問題,專案需要支援日文作業系統,但是沒有編譯成unicode程式。然後在乙個解析使用者輸入路徑的地方出問題了。原因是日文的 表 這個漢字,日文編碼格式下,低位元組和反斜槓 編碼一樣,解析的時候把它當成路徑的分隔符了。項 8d 80 shift jis 目 96 da shift jis ...
Unicode以及字符集轉換
曾經碰到乙個問題,專案需要支援日文作業系統,但是沒有編譯成unicode程式。然後在乙個解析使用者輸入路徑的地方出問題了。原因是日文的 表 這個漢字,日文編碼格式下,低位元組和反斜槓 編碼一樣,解析的時候把它當成路徑的分隔符了。項 8d 80 shift jis 目 96 da shift jis ...
Unicode字符集和多字符集
由於各國語言的加入,ascii已經不能滿足資訊交流的需要,因此,為了能夠表示其它國家的文字,各國在ascii的基礎上制定了自己的字符集,它們正式的名稱應該是mbcs multi byte chactacter system,即多位元組字元系統 型別說明 unicode ansi 通用型別 字元wch...