Unicode以及字符集轉換

2021-08-25 17:43:13 字數 3820 閱讀 7273

曾經碰到乙個問題,

專案需要支援日文作業系統,但是沒有編譯成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...