多字节与宽字节
- 多字節(jié)字符集(MBCS,Multi-Byte?Chactacter?Set):指用多個字節(jié)來表示一個字符的字符編碼集合。一般英文字母用1Byte,漢語等用2Byte來表示。兼容ASCII?127。
在最初的時候,Internet上只有一種字符集——ANSI的ASCII字符集,它使用7?bits來表示一個 字符,總共表示128個字符,其中包括了 英文字母、數(shù)字、標點符號等常用字符。
為了擴充ASCII編碼,以用于顯示本國的語言,不同的國家和地區(qū)制定了不同的標準,由此產生了 GB2312, BIG5, JIS 等各自的編碼標準。這些使用 2 個字節(jié)來代表一個字符的各種漢字延伸編碼方式,稱為 ANSI 編碼,又稱為"MBCS(Muilti-Bytes Charecter Set,多字節(jié)字符集)"。
不同 ANSI 編碼之間互不兼容,當信息在國際間交流時,無法將屬于兩種語言的文字,存儲在同一段 ANSI 編碼的文本中。一個很大的缺點是,同一個編碼值,在不同的編碼體系里代表著不同的字。這樣就容易造成混亂。導致了unicode碼的誕生。
- 寬字節(jié)字符集:一般指Unicode編碼的字符集,
Unicode稱為統(tǒng)一碼或萬國碼,統(tǒng)一了不同國家的字符編碼。
Unicode通常用兩個字節(jié)表示一個字符,原有的英文編碼從單字節(jié)變成雙字節(jié),只需要把高字節(jié)全部填為0就可以。
為了統(tǒng)一所有文字的編碼,Unicode應運而生。Unicode把所有語言都統(tǒng)一到一套編碼里,這樣就不會再有亂碼問題了。
Unicode固然統(tǒng)一了編碼方式,但是它的效率不高,比如UCS-4(Unicode的標準之一)規(guī)定用4個字節(jié)存儲一個符號,那么每個英文字母前都必然有三個字節(jié)是0,這對存儲和傳輸來說都很耗資源。為了提高Unicode的編碼效率,于是就出現(xiàn)了UTF-8編碼。UTF-8可以根據(jù)不同的符號自動選擇編碼的長短。比如英文字母可以只用1個字節(jié)就夠了。
UTF是“Unicode Transformation Format”的縮寫,可以翻譯成Unicode字符集轉換格式,即怎樣將Unicode定義的數(shù)字轉換成程序數(shù)據(jù)。用char、char16_t、char32_t分別表示無符號8位整數(shù),無符號16位整數(shù)和無符號32位整數(shù)。UTF-8、UTF-16、UTF-32分別以char、char16_t、char32_t作為編碼單位。(注: char16_t 和 char32_t 是 C++ 11 標準新增的關鍵字。如果你的編譯器不支持 C++ 11 標準,請改用 unsigned short 和 unsigned long。)“漢字”的UTF-8編碼需要3個字節(jié)。“漢字”的UTF-16編碼需要兩個char16_t,大小是2個字節(jié)。“漢字”的UTF-32編碼需要兩個char32_t,大小是4個字節(jié)。
普通字符、字符串前加 L 就變成寬字符 wchar_t 存儲(用2Byte存1個字符)了,例如,L‘看’,L"abc啊";或_T("sf飛")
MFC中的 CString 與 std::string 的轉換:
1. 使用Unicode字符集時,CString等價于CStringW;使用多字節(jié)字符集時,CString相對于CStringA
2. CString --> std::string
// 1. Unicode下 CString --> std::string // 方法1 CString str = L"sdf"; std::string s = CT2A(str.GetString());// GetString()比較新的VS有,舊可以用GetBuffer()std::string s = CT2A(str.GetBuffer());str.ReleaseBuffer(); // 方法2 CString str = L"dshf"; CStringA stra(str); std::string s(stra); //或 std::string s(CStringA(str));//方法3 USES_CONVERSION; CString str = L"djg"; std::string s = W2A(str); //首先str--》const wchar_t* ,然后W2A將const wchar_t*--》const char*, //最后用const char*初始化s?
?3. std::string --> CStringW / std::wstring
std::string s("dhhh"); CStringW strw(CStringA(s.c_str()); std::wstring sw(strw);
1)TCHAR 轉換為const wchar_t *,直接強制轉換,在TCHAR前面加上(*const?wchar_t)
2)BSTR:是一個OLECHAR*類型的Unicode字符串,是一個COM字符串,帶長度前綴,與VB有關,沒怎么用到過。?
LPSTR:即 char *,指向以'/0'結尾的8位(單字節(jié))ANSI字符數(shù)組指針?
LPWSTR:即wchar_t *,指向'/0'結尾的16位(雙字節(jié))Unicode字符數(shù)組指針?
?LPCSTR:即const char *?
?LPCWSTR:即const wchar_t *?
LPTSTR:LPSTR、LPWSTR兩者二選一,取決于是否宏定義了UNICODE或ANSI?
LPCTSTR: LPCSTR、LPCWSTR兩者二選一,取決于是否宏定義了UNICODE或ANSI,
如下是從MFC庫中拷來的:
#ifdef UNICODE typedef LPWSTR LPTSTR; typedef LPCWSTR LPCTSTR; #else typedef LPSTR LPTSTR; typedef LPCSTR LPCTSTR; #endif
?相互轉換方法:
LPWSTR->LPTSTR: ? W2T();
?LPTSTR->LPWSTR: ?T2W();?
LPCWSTR->LPCSTR: W2CT();
?LPCSTR->LPCWSTR: T2CW();
?ANSI->UNICODE: A2W();
?UNICODE->ANSI: W2A();
3)
LPWSTR轉為LPCSTR
LPCSTR=CW2A(LPWSTR);
?4)
CString與LPCWSTR的轉化(http://www.cnblogs.com/foolboy/archive/2005/07/25/199869.html)
問題起因:?
??? 在寫WritePrivateProfileString寫.ini配置文件時在msdn中看到,如果想要寫的配置信息即時生效,必須在之前使用WritePrivateProfileStringW來re-read一下目標.ini文件,其原文如下:?
??? 查了一下msdn中WritePrivateProfileStringW的原型如下:?
WINBASEAPI BOOL WINAPI WritePrivateProfileStringW ( LPCWSTR lpAppName, //section []中的字符串LPCWSTR lpKeyName, // key “=”左邊的字符串LPCWSTR lpString, //寫入的內容LPCWSTR lpFileName ) // 配置文件的路徑 例如: [section] key=string其中的每個參數(shù)的類型都為LPCWSTR,實際中獲得的文件名都為CString,問題產生。?
問題分析:
LPCWSTR 是Unicode字符串指針,初始化時串有多大,申請空間就有多大,以后存儲若超過則出現(xiàn)無法預料的結果,這是它與CString的不同之處。而CString是一個串類,內存空間類會自動管理。LPCWSTR?初始化如下:?
LPCWSTR Name=L"TestlpCwstr";????由于LPCWSTR必須指向Unicode的字符串,問題的關鍵變成了Anis字符與Unicode字符之間的轉換,不同編碼間的轉換,通過查找資料可知,可以ATL中轉換宏可以用如下方法實現(xiàn):?
//方法一 CString str=_T("TestStr"); USES_CONVERSION; LPWSTR pwStr=new wchar_t[str.GetLength()+1]; wcscpy(pwStr,T2W((LPCTSTR)str));// 方法二 CString str=_T("TestStr"); USES_CONVERSION; LPWCSTR pwcStr = A2CW((LPCSTR)str);??MFC中CString和LPSTR是可以通用,其中A2CW表示(LPCSTR)? -> (LPCWSTR),USER_CONVERSION表示用來定義一些中間變量,在使用ATL的轉換宏之前必須定義該語句。?
??? 順便也提一下,如果將LPCWSTR轉換成CString,那就更加容易,在msdn中的CString類說明中提到了可以直接用LPCWSTR來構造CString,所以可以進行如下的轉換代碼:???
LPCWSTR?pcwStr?=?L"TestpwcStr";?
CString?str(pcwStr);
問題總結:?????
????在頭文件<atlconv.h>中定義了ATL提供的所有轉換宏,如:????
??A2CW ? ? ?(LPCSTR)??->?(LPCWSTR)?
??A2W????????(LPCSTR)??->?(LPWSTR)?
??W2CA ? ? (LPCWSTR)?->?(LPCSTR)?
??W2A????????(LPCWSTR)?->?(LPSTR)
?????所有的宏如下表所示:?
| A2BSTR | OLE2A | T2A | W2A |
| A2COLE | OLE2BSTR | T2BSTR | W2BSTR |
| A2CT | OLE2CA | T2CA | W2CA |
| A2CW | OLE2CT | T2COLE | W2COLE |
| A2OLE | OLE2CW | T2CW | W2CT |
| A2T | OLE2T | T2OLE | W2OLE |
| A2W | OLE2W | T2W | W2T |
上表中的宏函數(shù),非常的有規(guī)律,每個字母都有確切的含義如下:
| 2 | to 的發(fā)音和 2 一樣,所以借用來表示“轉換為、轉換到”的含義。 |
| A | ANSI 字符串,也就是 MBCS。 |
| W、OLE | 寬字符串,也就是 UNICODE。 |
| T | 中間類型T。如果定義了 _UNICODE,則T表示W(wǎng);如果定義了 _MBCS,則T表示A |
| C | const 的縮寫 |
??? 利用這些宏,可以快速的進行各種字符間的轉換。使用前必須包含頭文件,并且申明USER_CONVERSION;使用 ATL 轉換宏,由于不用釋放臨時空間,所以使用起來非常方便。但是考慮到棧空間的尺寸(VC 默認2M),使用時要注意幾點:?
??? 1、只適合于進行短字符串的轉換;?
??? 2、不要試圖在一個次數(shù)比較多的循環(huán)體內進行轉換;?
??? 3、不要試圖對字符型文件內容進行轉換,因為文件尺寸一般情況下是比較大的;?
??? 4、對情況 2 和 3,要使用 MultiByteToWideChar() 和 WideCharToMultiByte();
MultiByteToWideChar() 和 WideCharToMultiByte()的用法:
www.cnblogs.com/ranjiewen/p/5770639.html
轉載于:https://www.cnblogs.com/htj10/p/11027323.html
總結
- 上一篇: WCF的CommunicationObj
- 下一篇: Magento多图导入