0 前言
在平時的開發(fā)過程中大部分人應該都遇到過中文亂碼問題,瀏覽網(wǎng)頁時也會遇到內(nèi)容顯示亂碼的情況解愤,一般遇到這種情況我們想到的可能是編碼問題镇饺。那我們說的編碼具體是指什么,亂碼問題的根本原因是什么送讲,又該如何解決呢奸笤?
答案的關(guān)鍵就是本文接下來要介紹的字符集與字符編碼。
1 概述
首先介紹一下字符哼鬓,字節(jié)揭保,字符串,字符集和字符編碼等基本概念魄宏。
- 字符(Character): 各種文字和符號的總稱,包括各國家文字存筏、標點符號宠互、圖形符號、數(shù)字等椭坚。
- 字節(jié)(Byte): 計算機信息技術(shù)用于計量存儲容量的一種計量單位予跌,也表示一些計算機編程語言中的數(shù)據(jù)類型和語言字符。
- 字符串(string): 一個連續(xù)的字符序列善茎,在存儲上類似于字符數(shù)組券册。
- 字符集(Character Set): 多個字符的集合,字符集種類較多垂涯,每個字符集包含的字符個數(shù)不同烁焙。
- 字符編碼(Character encoding): 也稱字集碼,是把字符集中的字符編碼為指定集合中某一對象(例如:比特模式耕赘、自然數(shù)序列骄蝇、8位組或者電脈沖),以便文本在計算機中存儲和通過通信網(wǎng)絡的傳遞操骡。
- 單字節(jié)字符集(Single Byte Character Set, SBCS): 所有字符都只用一個字節(jié)表示九火。用一個字節(jié)表示的0來標志SBCS字符串的結(jié)束赚窃。
- 多字節(jié)字符集(Multi-Byte Character Set, MBCS):部分字符用一個字節(jié)表示,部分字符用兩個或更多字節(jié)表示岔激。Windows中的MBCS包含兩種字符勒极,單字節(jié)字符(Single-Byte Characters)和雙字節(jié)字符(Double-Byte Characters)。有一些特定的值被保留用來表明它們是雙字節(jié)字符的一部分虑鼎。MBCS字符串也使用單字節(jié)的0來標志字符串結(jié)束辱匿。
- Unicode字符集: 通常又稱為寬字符集(Wide Character Set),所有字符都用兩個字節(jié)來表示震叙。 注意掀鹅,不要混淆Unicode字符集與MBCS,Unicode字符串采用兩個字節(jié)表示的0作為結(jié)束標志媒楼。
常見的字符集有:ASCII字符集乐尊、GB2312字符集、GBK字符集划址、Big5字符集扔嵌、GB18030字符集、Unicode字符集等夺颤。
一般情況下一個字符集對應一種字符編碼痢缎,但是Unicode比較特殊,存在多種字符編碼標準世澜,比如:UTF-7独旷,UTF-8,UTF-16寥裂,UTF-32等嵌洼。
根據(jù)各個字符集的特性及發(fā)展歷程可以將其劃分成三類,如下圖所示:
上圖中只列舉了幾種常見的字符集與字符編碼封恰,更多內(nèi)容請參閱字符編碼麻养。
注意: 平時與人溝通的時候要弄清楚自己說的是字符集還是字符編碼,尤其是在談論Unicode的時候诺舔。
2 ASCII
- ASCII(American Standard Code for Information Interchange鳖昌,美國信息互換標準編碼)是基于羅馬字母表的一套電腦編碼系統(tǒng)。
- 包含了英文大小寫字符低飒、阿拉伯數(shù)字和西文符號等可顯示字符以及回車鍵许昨、退格、換行鍵等控制字符褥赊。
- 主要用于顯示現(xiàn)代英語和其他西歐語言车要,是現(xiàn)今最通用的單字節(jié)編碼系統(tǒng),并等同于國際標準ISO 646崭倘。
- 基本字符集采用7位(bits)表示一個字符翼岁,共128個字符类垫,字符值從0到127,其中32到126是可打印字符琅坡。
- 擴展字符集采用8位(bits)表示一個字符悉患,共256個字符,增加了表格符號榆俺、計算符號售躁、希臘字母和特殊的拉丁符號,可以表示更多的歐洲常用字符茴晋。
3 ANSI(GB2312, GBK, Big5, GB18030)
隨著計算機的不斷普及陪捷,原來的ASCII單字節(jié)編碼已經(jīng)無法滿足世界各地的字符表示要求,于是诺擅,各個國家和地區(qū)都設(shè)計了一系列滿足于本國和地區(qū)的字符集與字符編碼市袖。
以中國為例,為了滿足國內(nèi)計算機使用漢字的需求烁涌,中國國家標準總局發(fā)布了一系列的漢字字符集國家標準編碼苍碟,統(tǒng)稱為GB碼,或國標碼撮执。
3.1 GB2312
GB2312是一個簡體中文字符集微峰,采用了二維矩陣編碼法對所有字符進行編碼:
- 首先構(gòu)造一個94行94列的方陣,對每一行稱為一個“區(qū)”抒钱,每一列稱為一個“位”蜓肆,
- 然后將所有字符依照下表的規(guī)律填寫到方陣中。
分區(qū)范圍 | 符號類型 |
---|---|
第01區(qū) | 中文標點谋币、數(shù)學符號以及一些特殊字符 |
第02區(qū) | 各種各樣的數(shù)學序號 |
第03區(qū) | 全角西文字符 |
第04區(qū) | 日文平假名 |
第05區(qū) | 日文片假名 |
第06區(qū) | 希臘字母表 |
第07區(qū) | 俄文字母表 |
第08區(qū) | 中文拼音字母表 |
第09區(qū) | 制表符號 |
第10-15區(qū) | 無字符 |
第16-55區(qū) | 一級漢字(以拼音字母排序) |
第56-87區(qū) | 二級漢字(以部首筆畫排序) |
第88-94區(qū) | 無字符 |
這樣所有的字符在方陣中都有一個唯一的位置仗扬,這個位置可以用區(qū)號、位號合成表示瑞信,稱為字符的區(qū)位碼。
GB2312編碼采用兩個字節(jié)表示一個漢字穴豫,區(qū)碼和位碼分別占用一個字節(jié)凡简。由于區(qū)碼和位碼的取值范圍都是在1-94之間,同西文的存儲表示沖突精肃。為了與西文進行區(qū)別秤涩,存儲時將區(qū)位碼的每個字節(jié)分別加上A0H(160)轉(zhuǎn)換為存儲碼。以漢字“啊”為例司抱,區(qū)位碼為1601(1001H)筐眷,存儲碼為B0A1H,轉(zhuǎn)換過程如下:
區(qū)位碼 | 區(qū)碼轉(zhuǎn)換 | 位碼轉(zhuǎn)換 | 存儲碼 |
---|---|---|---|
1001H | 10H+A0H=B0H | 01H+A0H=A1H | B0A1H |
3.2 GBK
- GBK是GB2312的擴展习柠,K為擴展的漢語拼音中“擴”字的聲母匀谣。英文全稱Chinese Internal Code Specification照棋。
- 字符有一字節(jié)和雙字節(jié)編碼,00–7F范圍內(nèi)是第一個字節(jié)武翎,和ASCII保持一致烈炭,此范圍內(nèi)嚴格上說有96個文字和32個控制符號。
- 之后的雙字節(jié)中宝恶,前一字節(jié)是雙字節(jié)的第一位符隙。總體上說第一字節(jié)的范圍是81–FE(也就是不含80和FF)垫毙,第二字節(jié)的一部分領(lǐng)域在40–7E霹疫,其他領(lǐng)域在80–FE。編碼范圍如下所示:
- 雙字節(jié)符號可以表達的64K空間如下圖所示综芥。綠色和黃色區(qū)域是GBK的編碼丽蝎,紅色是用戶定義區(qū)域。沒有顏色區(qū)域是不正確的代碼組合毫痕。
3.3 Big5
- Big5又稱為大五碼或五大碼征峦,是一種繁體字編碼,主要在臺灣消请,香港和澳門等使用繁體字的地區(qū)使用栏笆。
- Big5采用雙字節(jié)表示一個字符,第一個字節(jié)稱為“高位字節(jié)”臊泰,第二個字節(jié)稱為“低位字節(jié)”蛉加。
- “高位字節(jié)”范圍0x81-0xFE,“低位字節(jié)”范圍0x40-0x7E缸逃,及0xA1-0xFE针饥。具體分區(qū)如下所示:
分區(qū) | 備注 |
---|---|
0x8140-0xA0FE | 保留給用戶自定義字符(造字區(qū)) |
0xA140-0xA3BF | 標點符號、希臘字母及特殊符號需频,包括在0xA259-0xA261丁眼,安放了九個計量用漢字:兙兛兞兝兡兣嗧瓩糎。 |
0xA3C0-0xA3FE | 預留昭殉。此區(qū)沒有開放作造字區(qū)用苞七。 |
0xA440-0xC67E | 常用漢字,先按筆劃再按部首排序挪丢。 |
0xC6A1-0xC8FE | 保留給用戶自定義字符(造字區(qū)) |
0xC940-0xF9D5 | 次常用漢字巩剖,亦是先按筆劃再按部首排序灵嫌。 |
0xF9D6-0xFEFE | 保留給用戶自定義字符(造字區(qū)) |
3.4 GB18030
GB18030是我國目前最新的變長多字節(jié)字符集,兼容GB2312,GBK以及Unicode3.1榆苞。主要特點如下:
- 采用變長多字節(jié)編碼,每個字可以由1個、2個或4個字節(jié)組成。
- 編碼空間龐大融柬,最多可定義161萬個字符。
- 支持中國國內(nèi)少數(shù)民族文字姥闭,不需要動用造字區(qū)丹鸿。
- 漢字收錄范圍包含繁體漢字以及日韓漢字。
GB18030包含三種長度的編碼:單字節(jié)的ASCII棚品、雙字節(jié)的GBK(略帶擴展)靠欢、以及用于填補所有Unicode碼位的四字節(jié)UTF區(qū)段。編碼范圍如下圖所示:
3.5 Unicode
不同的國家和地區(qū)制定了適用于本國和地區(qū)的字符表示標準铜跑,但是這些標準之間往往是不兼容的门怪,比如用GB18030編碼的文件通過阿拉伯文的編碼標準去解析,肯定是顯示一堆亂碼锅纺。同時掷空,隨著計算機科學和互聯(lián)網(wǎng)的不斷發(fā)展,軟件國際化逐漸成為了必然的趨勢囤锉。在此背景下坦弟,一種包含了世界各地絕大部分文字字符的通用字符集就應運而生了-Unicode字符集。
Unicode字符集是通用多八位編碼字符集(Universal Multiple-Octet Coded Character Set)的簡稱官地。它為每種語言中的每個字符設(shè)定了統(tǒng)一并且唯一的二進制編碼酿傍,以滿足跨語言、跨平臺進行文本轉(zhuǎn)換驱入、處理的要求赤炒。
下面簡單梳理一下Unicode的編碼方式與實現(xiàn)方式的相關(guān)知識。
3.5.1 編碼方式
Unicode存在兩種編碼方式亏较,分別是UCS-2和UCS-4莺褒。
- UCS-2: 采用兩個字節(jié)編碼,理論上最多可以表示216(65536)個字符雪情。
- UCS-4: 采用四個字節(jié)編碼遵岩,理論上最多可以表示232(2147483648)個字符,完全可以涵蓋所有語言的字符巡通。
將UCS-4的BMP去掉前面的兩個零字節(jié)就得到了UCS-2跪解。在UCS-2的兩個字節(jié)前加上兩個零字節(jié),就得到了UCS-4的BMP。而目前的UCS-4規(guī)范中還沒有任何字符被分配在BMP之外叉讥。
3.5.2 實現(xiàn)方式
Unicode的實現(xiàn)方式不同于編碼方式窘行。一個字符的Unicode編碼是確定的。但是在實際傳輸過程中图仓,由于不同系統(tǒng)平臺的設(shè)計不一定一致罐盔,以及出于節(jié)省空間的目的,對Unicode編碼的實現(xiàn)方式有所不同救崔。Unicode的實現(xiàn)方式稱為Unicode轉(zhuǎn)換格式(Unicode Transformation Format惶看,簡稱為UTF)。
常見的實現(xiàn)方式有UTF-8六孵,UTF-16纬黎,UTF-32等。
- UTF-8: 以8bits(1字節(jié))為單位對UCS進行編碼劫窒,可以用1到4個字節(jié)來表示一個字符本今,是一種字節(jié)變長度編碼方式。
- UTF-16: 以16bits(2字節(jié))為單位對UCS進行編碼主巍,可以用2字節(jié)或4字節(jié)來表示一個字符冠息,是一種字節(jié)變長度編碼方式。
- UTF-32: 以32bits(4字節(jié))為單位對UCS進行編碼孕索,用4字節(jié)來表示一個字符逛艰,是一種字節(jié)固定長度編碼方式。
UCS-2和UCS-4是編碼方案檬果,而UTF-x是編碼實現(xiàn)方式瓮孙,涉及到實際傳輸,所以需要考慮字節(jié)序問題选脊。
字節(jié)序(Byte Order Mark,BOM): 用于表示字節(jié)傳輸過程中的存儲方式杭抠,常見的實現(xiàn)方式及對應BOM如下所示:
UTF | BOM |
---|---|
UTF-8 | EF BB BF |
UTF-16LE | FF FE |
UTF-16BE | FE FF |
UTF-32LE | FF FE 00 00 |
UTF-32BE | 00 00 FE FF |
LE表示小端字節(jié)序,BE表示大端字節(jié)序恳啥。
3.5.3 UTF-8
由于UTF-16和UTF-32都存在空間浪費的情況偏灿,而UTF-8采用字節(jié)為單位的變長編碼方式,大大提高了空間利用率钝的,因此翁垂,UTF-8也是我們平時用的最多的編碼方式。
UTF-8的編碼規(guī)則有兩條:
- 對于單字節(jié)的符號硝桩,字節(jié)的第一位設(shè)為0沿猜,后面7位為這個符號的unicode碼。因此對于英語字母碗脊,UTF-8編碼和ASCII碼是相同的啼肩。
- 對于n字節(jié)的符號(n>1),第一個字節(jié)的前n位都設(shè)為1,第n+1位設(shè)為0祈坠,后面字節(jié)的前兩位一律設(shè)為10害碾。剩下的沒有提及的二進制位,全部為這個符號的unicode碼赦拘。
下表總結(jié)了編碼規(guī)則慌随,字母x表示可用編碼的位。
Unicode符號范圍(十六進制) | UTF-8編碼方式(二進制) |
---|---|
0000 0000-0000 007F | 0xxxxxxx |
0000 0080-0000 07FF | 110xxxxx 10xxxxxx |
0000 0800-0000 FFFF | 1110xxxx 10xxxxxx 10xxxxxx |
0001 0000-0010 FFFF | 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx |
4 字符編碼的應用
字符集與字符編碼相關(guān)的知識非常多躺同,上面只是簡單介紹了一些常見的字符集以及字符編碼阁猜。想要了解更多的知識可以點擊相關(guān)概念的鏈接進行深入研究。
接下來介紹一下平時開發(fā)中會涉及到編碼相關(guān)的一些知識點蹋艺。
4.1 代碼頁
代碼頁是字符集編碼的別名蹦漠,最早是IBM公司首先使用〕岛#可以將代碼頁理解為字符和字節(jié)數(shù)據(jù)的映射表笛园。
Windows中將支持的代碼頁用一個編號來表示。例如代碼頁936就是簡體中文GBK侍芝。
可以在DOS的CMD命令行下通過chcp命令進行查看和修改系統(tǒng)的代碼頁研铆。
# 查看代碼頁
C:\>chcp
活動代碼頁: 936
4.2 區(qū)域(Locale)設(shè)置
Microsoft為了適應世界各地的文化背景和使用習慣,在Winodows系統(tǒng)中設(shè)計了區(qū)域設(shè)置的功能州叠】煤欤可以通過控制面板->區(qū)域與語言
選項進行系統(tǒng)Locale和用戶Locale設(shè)置,其中系統(tǒng)Locale決定代碼頁咧栗;用戶Locale決定數(shù)字逆甜、貨幣、時間和日期格式致板。設(shè)置界面如下圖所示:
C++中有兩種方式可以設(shè)置區(qū)域信息交煞,如下:
- 通過setlocale函數(shù)在運行時設(shè)置區(qū)域信息。
- 通過#pragrma setlocale編譯指定來設(shè)置區(qū)域信息斟或,該指令在編譯時起作用素征。
4.3 VS中字符集設(shè)置
為了方便代碼的移植和統(tǒng)一,目前的開發(fā)環(huán)境一般都會采用Uincode字符集萝挤,在VS中可以通過Project->Properties->Configuration Properities->General->Character Set
進行設(shè)置御毅,如下圖所示:
4.4 C++中字符和字符串的相關(guān)知識
C++的新標準中引入了UTF-16和UTF-32編碼方式的字符,分別用小寫字母u和大寫字母U開頭來表示怜珍,同時也引入了更多的字符串類型與操作端蛆,直接看下MSDN提供的代碼示例:
#include <string>
using namespace std::string_literals; // enables s-suffix for std::string literals
int main()
{
// Character literals
auto c0 = 'A'; // char
auto c1 = u8'A'; // char
auto c2 = L'A'; // wchar_t
auto c3 = u'A'; // char16_t
auto c4 = U'A'; // char32_t
// String literals
auto s0 = "hello"; // const char*
auto s1 = u8"hello"; // const char*, encoded as UTF-8
auto s2 = L"hello"; // const wchar_t*
auto s3 = u"hello"; // const char16_t*, encoded as UTF-16
auto s4 = U"hello"; // const char32_t*, encoded as UTF-32
// Raw string literals containing unescaped \ and "
auto R0 = R"("Hello \ world")"; // const char*
auto R1 = u8R"("Hello \ world")"; // const char*, encoded as UTF-8
auto R2 = LR"("Hello \ world")"; // const wchar_t*
auto R3 = uR"("Hello \ world")"; // const char16_t*, encoded as UTF-16
auto R4 = UR"("Hello \ world")"; // const char32_t*, encoded as UTF-32
// Combining string literals with standard s-suffix
auto S0 = "hello"s; // std::string
auto S1 = u8"hello"s; // std::string
auto S2 = L"hello"s; // std::wstring
auto S3 = u"hello"s; // std::u16string
auto S4 = U"hello"s; // std::u32string
// Combining raw string literals with standard s-suffix
auto S5 = R"("Hello \ world")"s; // std::string from a raw const char*
auto S6 = u8R"("Hello \ world")"s; // std::string from a raw const char*, encoded as UTF-8
auto S7 = LR"("Hello \ world")"s; // std::wstring from a raw const wchar_t*
auto S8 = uR"("Hello \ world")"s; // std::u16string from a raw const char16_t*, encoded as UTF-16
auto S9 = UR"("Hello \ world")"s; // std::u32string from a raw const char32_t*, encoded as UTF-32
}
4.5 ANSI字符串與Unicode字符串相互轉(zhuǎn)換
Windows提供了一些列的API函數(shù)來操作字符串,包括獲取字符集信息酥泛,判斷是否是DBCS的起始字節(jié)以及ANSI字符串與Unicode字符串之間相互轉(zhuǎn)換等今豆。用的比較多的應該就是字符串轉(zhuǎn)換的API了侈沪,如下所示:
- MultiByteToWideChar: ANSI字符串轉(zhuǎn)換成Unicode字符串。
- WideCharToMultiByte: Unicode字符串轉(zhuǎn)換成ANSI字符串晚凿。
ANSI字符串又稱為多字節(jié)字符串,Unicode字符串又稱為寬字節(jié)字符串瘦馍。每個人的叫法習慣不同歼秽,知道對應的關(guān)系即可。
為了操作簡單情组,ATL提供了幾個宏用于字符串轉(zhuǎn)換燥筷,底層實現(xiàn)都是通過上述介紹的MultiByteToWideChar和WideCharToMultiByte兩個API。
平時用的最多的就是CA2T和CT2A院崇,這兩個宏中各個字母代表的含義如下所示:
字母 | 含義 |
---|---|
C | 目標類型必須是Const類型 |
A | ANSI字符串 |
W | Unicode字符串 |
T | 通用字符串肆氓,當定義了_UNICODE宏時T表示W(wǎng),否則T表示A |
使用這兩個宏的時候需要注意幾點:
- 作用域問題:CA2T和CT2A的轉(zhuǎn)換后的數(shù)據(jù)作用域只在當前行底瓣,即在下一行代碼中再去訪問轉(zhuǎn)換后的數(shù)據(jù)會出現(xiàn)不可預知的問題谢揪。如下代碼所示:
// 正確,F(xiàn)un函數(shù)使用轉(zhuǎn)換后的TCHAR
Fun(CA2T(szSrc, CP_UTF8));
// 正確捐凭,轉(zhuǎn)換后的數(shù)據(jù)賦值給strDes
CString strDes = CA2T(szSrc, CP_UTF8);
// 錯誤拨扶,轉(zhuǎn)換后的數(shù)據(jù)在下一行被釋放,即szDes指向的數(shù)據(jù)變成未知
TCHAR *szDes = CA2T(szSrc, CP_UTF8);
- 參數(shù)問題: 轉(zhuǎn)換過程中可以指定code page信息茁肠,下面是摘之winnls.h對應參數(shù)的描述:
// Code Page Default Values.
#define CP_ACP 0 // default to ANSI code page
#define CP_OEMCP 1 // default to OEM code page
#define CP_MACCP 2 // default to MAC code page
#define CP_THREAD_ACP 3 // current thread's ANSI code page
#define CP_SYMBOL 42 // SYMBOL translations
#define CP_UTF7 65000 // UTF-7 translation
#define CP_UTF8 65001 // UTF-8 translation
下面以CA2T為例患民,我們來看下底層實現(xiàn)是如何運用這些參數(shù)的。
// 1. CA2T其實轉(zhuǎn)化為CA2W
#define CA2T CA2W
// 2. CA2W又是通過模板CA2WEX來實現(xiàn)
typedef CA2WEX<> CA2W;
// 3. 下面是CA2WEX<>的模板實現(xiàn):
template< int t_nBufferLength = 128 >
class CW2AEX
{
public:
CW2AEX(_In_z_ LPCWSTR psz) throw(...)
:m_psz( m_szBuffer )
{
Init( psz, _AtlGetConversionACP() );
}
CW2AEX(_In_z_ LPCWSTR psz, _In_ UINT nCodePage) throw(...)
:m_psz( m_szBuffer )
{
Init( psz, nCodePage );
}
~CW2AEX() throw()
{
AtlConvFreeMemory(m_psz,m_szBuffer,t_nBufferLength);
}
_Ret_z_ operator LPSTR() const throw()
{
return( m_psz );
}
private:
void Init(_In_z_ LPCWSTR psz, _In_ UINT nConvertCodePage) throw(...)
{
if (psz == NULL)
{
m_psz = NULL;
return;
}
int nLengthW = lstrlenW( psz )+1;
int nLengthA = nLengthW*4;
AtlConvAllocMemory(&m_psz,nLengthA,m_szBuffer,t_nBufferLength);
BOOL bFailed=(0 == ::WideCharToMultiByte( nConvertCodePage, 0, psz, nLengthW, m_psz, nLengthA, NULL, NULL ));
if (bFailed)
{
if (GetLastError()==ERROR_INSUFFICIENT_BUFFER)
{
nLengthA = ::WideCharToMultiByte( nConvertCodePage, 0, psz, nLengthW, NULL, 0, NULL, NULL );
AtlConvAllocMemory(&m_psz,nLengthA,m_szBuffer,t_nBufferLength);
bFailed=(0 == ::WideCharToMultiByte( nConvertCodePage, 0, psz, nLengthW, m_psz, nLengthA, NULL, NULL ));
}
}
if (bFailed)
{
AtlThrowLastWin32();
}
}
public:
LPSTR m_psz;
char m_szBuffer[t_nBufferLength];
private:
CW2AEX(_In_ const CW2AEX&) throw();
CW2AEX& operator=(_In_ const CW2AEX&) throw();
};
inline UINT WINAPI _AtlGetConversionACP() throw()
{
#ifdef _CONVERSION_DONT_USE_THREAD_LOCALE
return CP_ACP;
#else
return CP_THREAD_ACP;
#endif
}
- 從上述的代碼邏輯中可以看出垦梆,當沒有指定轉(zhuǎn)換代碼頁的時候默認通過_AtlGetConversionACP函數(shù)來獲取轉(zhuǎn)換參數(shù)匹颤。
- 注意區(qū)別CP_ACP和CP_THREAD_ACP,大多數(shù)情況下這兩者對應的代碼頁是一樣的,都是系統(tǒng)當前的代碼頁托猩,但是如果程序在運行時指定了其它的代碼頁則會出現(xiàn)不一致的情況印蓖。
- CP_ACP代表的是系統(tǒng)當前的代碼頁,但是不同系統(tǒng)中當前的代碼頁可能是不一樣的京腥,例如A電腦設(shè)置的是936(簡體中文)另伍,B電腦設(shè)置的是950(繁體中文),此時將一個簡體中文字符串進行轉(zhuǎn)換時在A電腦上可以成功绞旅,但是在B電腦上就出現(xiàn)了亂碼情況摆尝。因此,建議采用CP_UTF8參數(shù)對字符串進行轉(zhuǎn)換因悲,降低出現(xiàn)亂碼的概率堕汞。
更多詳細內(nèi)容請參閱ATL and MFC String Conversion Macros。
5 總結(jié)
字符集和字符編碼相關(guān)的知識非常多晃琳,本文主要梳理總結(jié)了一些常用的讯检、比較核心的概念琐鲁,希望對大家有所幫助。
整理這篇文章的過程中查看了非常多的資料人灼,主要是維基百科和MSDN文檔围段,大部分可以通過文中超鏈接跳轉(zhuǎn)過去,還有一些博客對字符編碼的介紹投放,下面列舉一些個人覺得總結(jié)的不錯的文章作為補充閱讀奈泪。