字符編碼和字符集

  1.  字符編碼 (Character encoding)
在存儲和傳遞文本過程中,爲了使得所有電腦都能夠正確的識別出文本內容,需要有一個統一的規則。

2.  字符集 (Character Set) )

一般情況,一種編碼方式對應一種字符集。如 ASCII,對應 ASCII 字符集。GBK 編碼方式對應 GBK 字符集。但是也有一種編碼方式,多種字符集的,Unicode 字符集有多種編碼方式,如 utf-8,utf-16 等。
. 3.  ASCII
ASCII(American Standard Code for Information Interchange,美國信息交換標準代碼):使用 7 個 Bit 表示,共 128 個字符,剛好佔用了一個字節中的後 7 位,共包括33 個控制字符和 95 個可顯示字符。
. 4.  ANSI
ANSI (一種字符編碼,此處不是表示美國國家標準學會的意思):ANSI 是爲了讓計算機支持更多的語言,而在 ASCII 的基礎上的一種擴展字符編碼。在不同語言操作上,ANSI 都表示當前計算機默認的編碼方式。如在簡體 Windows 操作下,ANSI 編碼代表 GBK 編碼;在繁體中文操作下,ANSI 編碼代表 Big5 編碼;在日文 Windows 操作系統中,ANSI 編碼代表 Shift_JIS 編碼;在英文操作系統下,ANSI 就是 ASCII 編碼。
. 5.  MBCS
MBCS(Multi-Byte Character Set),早在 1980 年,中國就提出了使用 GB2312 編碼方式來描述漢字。後來其他東亞國家也利用這種方式擴展 ASCII 編碼字符集。臺灣地區 5 大
企業推出的繁體 Big5 碼,香港新加坡等後來也利用。日本韓國也相應推出了自己的編碼方式。其實在這裏,BIG5 既是編碼方式,也是字符集。
. 6.  GB2312(Guo Biao  2312) )
用雙字節表示漢字,但是爲了完全兼容 ASCII。漢字區“高字節”範圍爲 0xB0-0xF7,漢字區“低字節”範圍 0xA1-0xFE,佔用的碼位 72*94=6768 個。
. 7.  GBK(Guo Biao Kuozhan)
後來發現 GB2312 的字符依然不夠用,尤其是像“鎔”(朱鎔基)字打不出來。然後決定漢字區的低字節完全不兼容 ASCII,只要當前字符屬於漢字碼,那麼其後的字符也屬於漢字碼。這樣在兼容 GB2312 的基礎上,再添加了近兩萬字和字符(兼容繁體、日本漢字、韓國漢字等)。GBK 同樣也是一種編碼方式和字符集兩種意義合於一體。
. 8.  GB18030
有兩版 GB18030-2000 和 GB18030-2005,是 GBK 的擴展版,並且完全兼容 GBK。GB18030和 utf-8 類似,是動態的,既有單字節字體,也有雙字節字節(BGK),也有三字節,四字節字符。Windows 默認支持的是 GBK,若要支持 GB18030,需要下載安裝單獨的支持包。
. 9.  Big5 5
1984 年臺灣五家公司聯合創立,稱大五碼,英文 Big5。Big5 也是雙字節編碼方式,收錄了一萬多字符,但是沒有包含中文簡體。Big5 目前也被香港、新家坡等地區國家使用。Big5 保存的文本,在簡體操作系統下顯示亂碼,但是有些編輯器會自動識別,然後將其按 GBK 繁體字顯示,即可正常顯示。如 Notepad++即有此功能。
10.  全角
GBK 用兩個字節重新表示了一遍在 ASCII 中出現的字符,這些字符被叫全角字符。
11.  半角
出現在 ASCII 中的字符,被稱作半角字符。
12. e Unicode  字符集
Unicode 字符集是 1990 年提出的,能夠表示全世界所有國家的所有字符。但是支持Unicode 字符集的編碼方式都有多種,如 UTF-8,UTF-16 等。編碼方式雖然不同,但是
都是可以完整表示所有 Unicode 字符的。VS 裏默認的 Unicode 字符集是指 utf-16 編碼的,即固定雙字節爲一個字符。
13.  UTF- -8 8
因爲 Unicode 能夠包含全球所有的字符,而 utf-8 又是其中比較節省字符存儲的一種實現方式。所以現在的網站,基本都是以 utf-8 編碼方式來存儲、傳輸和顯示了。UTF-8
是變字節長度的,用 1-6 個字節表示字符。用一個字符表示常見字符,用二個字節表示拉丁文、希臘文、西裏爾字母、亞美尼亞語、希伯來文、阿拉伯文、敘利亞等,用三字
符表示常見漢字等,四個字節的字符比較少見。UTF-8 既能很方便存儲英文,又能兼容全世界的字符,所以非常流行。
14.  UTF- -8 8  解析算法
如果字節的第一位爲 0,則 B 爲 ASCII 碼,並且 Byte 獨立的表示一個字符;
如果字節的第一位爲 1,第二位爲 0,則 Byte 爲一個非 ASCII 字符(該字符由多個字節表示)中的一個字節,並且不爲字符的第一個字節編碼;
如果字節的前兩位爲 1,第三位爲 0,則 Byte 爲一個非 ASCII 字符(該字符由多個字節
表示)中的第一個字節,並且該字符由兩個字節表示;
如果字節的前三位爲 1,第四位爲 0,則 Byte 爲一個非 ASCII 字符(該字符由多個字節表示)中的第一個字節,並且該字符由三個字節表示;
如果字節的前四位爲 1,第五位爲 0,則 Byte 爲一個非 ASCII 字符(該字符由多個字節
表示)中的第一個字節,並且該字符由四個字節表示代碼頁(CodePag):代碼頁是字符集的數字值,不同的語言使用不同的代碼頁。例 如,ANSI
代碼頁爲 1252,日文代碼頁爲 932,簡體中文(GBK)代碼頁爲 936,繁體中文(Big5)代碼頁爲 950。
15.  語言包
系統默認的是 ANSI,但是同時也兼容 Unicode,這也是 Windows 的 API 有兩套。當系統識別到當前字符是 Unicode 時,會以對應的 Unicode 編碼方式去解碼,Windows 支持的是 utf-8。解碼之後,需要正確地顯示出相應的字形,這個時候就需要語言包。如果沒有語言包,會出現亂碼。英文操作下,東亞語言歸爲一類,需要單獨安裝,安裝時提示230MB。因爲語言包比較大,所以在英文操作系統下,默認沒有安裝東亞語言包的,即不能正確顯示 Unicode 下的東亞文字。至於語言包爲什麼這麼大,猜測語言包必須得描述這個字體是如何點鉤撇捺的等等。Windows 可以在控制面板中設置非 Unicode 程序顯示語言。
16.  大小端模式
由於 CPU 的緣故,存取數據分大端模式和小端模式,然後一些操作系統了軟件也會有這樣的區分。大端模式(Big-endian),是指數據的高字節,保存在內存的低地址中,而
數據的低字節,保存在內存的高地址中,這樣的存儲模式有點兒類似於把數據當作字符串順序處理:地址由小向大增加,而數據從高位往低位放。小端模式(Little-endian),
是指數據的高字節保存在內存的高地址中,而數據的低字節保存在內存的低地址中,這種存儲模式將地址的高低和數據位權有效地結合起來,高地址部分權值高,低地址部分
權值低,和我們的邏輯方法一致。
17.  BOM(Byte Order Mark, 字節順序標記) )
有一些文本編輯工具支持 UTF-8(BOM),字符 U+FEFF 如果出現在字節流的開頭,則用來標識該字節流的字節序,是高位在前還是低位在前。接收者收到 FEFF,就表明這個字節
流是 Big-Endian 的;如果收到 FFFE,就表明這個字節流是 Little- Endian 的。Windows 文本默認的 Unicode 爲大端 utf-16 存儲,即以 FFFE 開頭。BOM 主要應用Windows 下,而在某些系統下可能會出錯,如 PHP 中容易讀錯。

編碼  以此標記 (十六進制)  以此標記 (十進制)
UTF-8 EF BB BF 239 187 191
UTF-16(大端序) FE FF 254 255
UTF-16(小端序) FF FE 255 254
UTF-32(大端序) 00 00 FE FF 0 0 254 255
UTF-32(小端序) FF FE 00 00  255 254 0 0 
18.  GBK 、e Unicode 他 他  UTF- -8 8  轉換
UTF-8 和 GBK 同屬於多字節 MultiByte,Unicode 默認是 UTF-16,即寬字符,兩個字節。

GBK(ANSI)->Unicode->UTF-8,反向即 UTF-8->Unicode->GBK(ANSI)。

  1. // 註釋:多字節包括GBK和UTF-8  
    int GBK2UTF8(char *szGbk,char *szUtf8,int Len)  
    {  
        // 先將多字節GBK(CP_ACP或ANSI)轉換成寬字符UTF-16  
        // 得到轉換後,所需要的內存字符數  
        int n = MultiByteToWideChar(CP_ACP,0,szGbk,-1,NULL,0);  
        // 字符數乘以 sizeof(WCHAR) 得到字節數  
        WCHAR *str1 = new WCHAR[sizeof(WCHAR) * n];  
        // 轉換  
        MultiByteToWideChar(CP_ACP,  // MultiByte的代碼頁Code Page  
            0,            //附加標誌,與音標有關  
            szGbk,        // 輸入的GBK字符串  
            -1,           // 輸入字符串長度,-1表示由函數內部計算  
            str1,         // 輸出  
            n             // 輸出所需分配的內存  
            );  
      
        // 再將寬字符(UTF-16)轉換多字節(UTF-8)  
        n = WideCharToMultiByte(CP_UTF8, 0, str1, -1, NULL, 0, NULL, NULL);  
        if (n > Len)  
        {  
            delete[]str1;  
            return -1;  
        }  
        WideCharToMultiByte(CP_UTF8, 0, str1, -1, szUtf8, n, NULL, NULL);  
        delete[]str1;  
        str1 = NULL;  
      
        return 0;  
    }

    //UTF-8 GBK  
    int UTF82GBK(char *szUtf8,char *szGbk,int Len)  
    {  
        int n = MultiByteToWideChar(CP_UTF8, 0, szUtf8, -1, NULL, 0);  
        WCHAR * wszGBK = new WCHAR[sizeof(WCHAR) * n];  
        memset(wszGBK, 0, sizeof(WCHAR) * n);  
        MultiByteToWideChar(CP_UTF8, 0,szUtf8,-1, wszGBK, n);  
      
        n = WideCharToMultiByte(CP_ACP, 0, wszGBK, -1, NULL, 0, NULL, NULL);  
        if (n > Len)  
        {  
            delete[]wszGBK;  
            return -1;  
        }  
      
        WideCharToMultiByte(CP_ACP,0, wszGBK, -1, szGbk, n, NULL, NULL);  
      
        delete[]wszGBK;  
        wszGBK = NULL;  
      
        return 0;  
    }

    19. 附ASCII碼圖表



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章