1.字符編碼的發展
第一階段:ASCII階段,(American Standard Code for Information Interchange, “美國信息交換標準碼),計算機當時只支持英語,字符在計算機中都是以0和1的方式存儲的。象a、b、c、d這樣的52個字母(包括大寫)、以及0、1、2等數字還有一些常用的符號(例如*、#、@等)在計算機中存儲時也要使用二進制數來表示,而具體用哪些二進制數字表示哪個符號,就必須要有一定的規則,於是美國有關的標準化組織就出臺了所謂的ASCII編碼,統一規定了上述常用符號用哪個二進制數來表示。(來自百度百科),ASCII碼規定每個字符例如“a”使用1個字節來表示,也就是8爲的二進制組合,那麼就有00000000-11111111一共256種組合,也就是可以表示256個不同的字符。
其中0-31:是控制字符或通訊專用字符(不可以顯示的字符,其餘爲可顯示字符),如控制符:LF(換行)、CR(回車)等。
32-126:是字符,其中32是空格。
48-57爲0-9的阿拉伯數字。
65-90爲26個大寫英文字母。
97-122爲26個小寫英文字母。
其餘的是一些標點符號,運算符號等。
ASSCII共計有128個,從0到127,也就是從00000000-01111111,最高位都是0。
第二階段:ANSI編碼(本地化)階段,ASCII只能表示英文字符,那麼其他字符怎麼表示呢?漢語是這樣解決的,用兩個ASCII表示一個漢字,而且不用前面的128個。比如漢字“中”在中文操作系統中使用[0xD6,0xD0] 這兩個字節存儲,這樣每個漢字也都有了自己的編碼,漢字編碼解決了,這就是中國的GB2312編碼標準,但是這是中國漢字的編碼,那麼其他國家呢?其他的國家的計算機操作系統中可能把[0xD6,0xD0] 這兩個字節存儲成他們的文字,而不是“中”,不同的國家和地區制定了不同的標準,這些使用 2 個字節來代表一個字符的各種文字延伸編碼方式,稱爲 ANSI 編碼。
“大”的國際交換碼:(00110100 01110011),內碼是:10110100 11110011(B4F3)
第三階段:UNICODE(國際化),爲了使國際間信息交流更加方便,國際組織制定了 UNICODE 字符集,爲各種語言中的每一個字符設定了統一併且唯一的數字編號,以滿足跨語言、跨平臺進行文本轉換、處理的要求。Unicode用數字0-0x10FFFF來映射這些字符,最多可以容納1114112個字符,或者說有1114112個碼位。碼位就是可以分配給字符的數字。UTF-8、UTF-16、UTF-32都是將數字轉換到程序數據的編碼方案。
Unicode目前普遍採用的是UCS-2它用兩個字節來編碼一個字符一般用十六進制來表示UCS-2最多能編碼65536個字符
環境:win7中文旗艦版 + VS2010 + 當前代碼頁爲GBK(GBK兼容GB2312,所以上面的例子,可以再當前環境下驗證)
string str1 = "123大";//GBK編碼[31H,32H,33H,b4H,f3H]
wstring str2 = L"123大";//UCS-2編碼[0031H,0032H,0033H,5927H]
string str3;
int nlength = WideCharToMultiByte(CP_UTF8, 0, str2.c_str(), -1, NULL, 0, NULL, NULL);
str3.resize(nlength, '\0');
WideCharToMultiByte(CP_UTF8, 0, str2.c_str(), -1, &str3[0], nlength, NULL, NULL);//Unicode to UTF-8
//str2 UTF-8編碼[31H,32H,33H,E5H,a4H,a7H]
1)對於單字節的符號,字節的第一位設爲0,後面7位爲這個符號的unicode碼。因此對於英語字母,UTF-8編碼和ASCII碼是相同的。
2)對於n字節的符號(n>1),第一個字節的前n位都設爲1,第n+1位設爲0,後面字節的前兩位一律設爲10。剩下的沒有提及的二進制位,全部爲這個符號的unicode碼。
例如:
“大”字,UCS-2編碼爲[5927H],即[0101 1001 0010 0111]
對於UTF-8編碼來說,[5927H]在0800H~FFFFH之間,應該使用[1110 xxxx 10yy yyyy 10zz zzzz],將[0101 1001 0010 0111]以此填入xxxx yy yyyy zz zzzz部分,得
[1110 0101 1010 0100 1010 0111],即 [e5H a4H a7H]