C++ 編碼轉換

來源:互聯網
上載者:User

標籤:

一 預備知識 
1,字元:字元是抽象的最小文本單位。它沒有固定的形狀(可能是一個字形),而且沒有值。“A”是一個字元,“€”(德國、法國和許多其他歐洲國家通用貨幣的標誌)也是一個字元。“中”“國”這是兩個漢字字元。字元僅僅代表一個符號,沒有任何實際值的意義。 
2,字元集:字元集是字元的集合。例如,漢字字元是中國人最先發明的字元,在中文、日文、韓文和越南文的書寫中使用。這也說明了字元和字元集之間的關係,字元組成字元集(iso8859-1,GB2312/GBK,unicode)。 
3,代碼點:字元集中的每個字元都被分配到一個“代碼點”。每個代碼點都有一個特定的唯一數值,稱為標值。該標量值通常用十六進位表示。 
4,代碼單元: 在每種編碼形式中,代碼點被映射到一個或多個代碼單元。“代碼單元”是各個編碼方式中的單個單元。代碼單元的大小等效於特定編碼方式的位元: 
UTF-8 :UTF-8 中的代碼單元由 8 位組成;在 UTF-8 中,因為代碼單元較小的緣故,每個代碼點常常被映射到多個代碼單元。代碼點將被映射到一個、兩個、三個或四個代碼單元; 
UTF-16 :UTF-16 中的代碼單元由 16 位組成;UTF-16 的代碼單元大小是 8 位代碼單元的兩倍。所以,標量值小於 U+10000 的代碼點被編碼到單個代碼單元中; 
UTF-32:UTF-32  中的代碼單元由 32 位組成; UTF-32 中使用的 32 位代碼單元足夠大,每個代碼點都可編碼為單個代碼單元; 
GB18030:GB18030  中的代碼單元由 8 位組成;在 GB18030 中,因為代碼單元較小的緣故,每個代碼點常常被映射到多個代碼單元。代碼點將被映射到一個、兩個或四個代碼單元。 
5,舉例: 
“中國北京香蕉是個大笨蛋”這是我定義的aka字元集;各字元對應代碼點為: 
北 00000001 
京 00000010 
香 10000001 
蕉 10000010 
是 10000100 
個 10001000 
大 10010000 
笨 10100000 
蛋 11000000 
中 00000100 
國 00001000 
下面是我定義的 zixia 編碼方案(8位),可以看到它的編碼中表示了aka字元集的所有字元對應的 代碼單元; 
北 10000001 
京 10000010 
香 00000001 
蕉 00000010 
是 00000100 
個 00001000 
大 00010000 
笨 00100000 
蛋 01000000 
中 10000100 
國 10001000 
所謂文字檔 就是我們按一定編碼方式將位元據表示為對應的文本如 00000001000000100000010000001000000100000010000001000000這樣的檔案。我用一個支援 zixia編碼和aka字元集的記事本開啟,它就按照編碼方案顯示為  “香蕉是個大笨蛋 ” 
如果我把這些字元按照GBK另存一個檔案,那麼則肯定不是這個,而是 
1100111111100011 1011110110110110 1100101011000111 1011100011110110 1011010011110011 1011000110111111 1011010110110000 110100001010 
二,字元集 
1, 常用字元集分類 
ASCII及其擴充字元集 
作用:表語英語及西歐語言。 
位元:ASCII是用7位表示的,能表示128個字元;其擴充使用8位表示,表示256個字元。 
範圍:ASCII從00到7F,擴充從00到FF。 
ISO-8859-1字元集 
作用:擴充ASCII,表示西歐、希臘語等。 
位元:8位, 
範圍:從00到FF,相容ASCII字元集。 
GB2312字元集 
作用:國家簡體中文字元集,相容ASCII。 
位元:使用2個位元組表示,能表示7445個符號,包括6763個漢字,幾乎覆蓋所有高頻率漢字。 
範圍:高位元組從A1到F7, 低位元組從A1到FE。將高位元組和低位元組分別加上0XA0即可得到編碼。 
BIG5字元集 
作用:統一繁體字編碼。 
位元:使用2個位元組表示,表示13053個漢字。 
範圍:高位元組從A1到F9,低位元組從40到7E,A1到FE。 
GBK字元集 
作用:它是GB2312的擴充,加入對繁體字的支援,相容GB2312。 
位元:使用2個位元組表示,可表示21886個字元。 
範圍:高位元組從81到FE,低位元組從40到FE。 
GB18030字元集 
作用:它解決了中文、日文、朝鮮語等的編碼,相容GBK。 
位元:它採用變位元組表示(1 ASCII,2,4位元組)。可表示27484個文字。 
範圍:1位元組從00到7F; 2位元組高位元組從81到FE,低位元組從40到7E和80到FE;4位元組第一三位元組從81到FE,第二四位元組從30到39。 
UCS字元集 
作用:國際標準 ISO 10646 定義了通用字元集 (Universal Character Set)。它是與UNICODE同類的組織,UCS-2和UNICODE相容。 
位元:它有UCS-2和UCS-4兩種格式,分別是2位元組和4位元組。 
範圍:目前,UCS-4隻是在UCS-2前面加了0×0000。 
UNICODE字元集 
作用:為世界650種語言進行統一編碼,相容ISO-8859-1。 
位元:UNICODE字元集有多個編碼方式,分別是UTF-8,UTF-16和UTF-32。 
2 ,按所表示的文字分類 
語言                                 字元集                                     正式名稱 
英語、西歐語                     ASCII,ISO-8859-1                MBCS 多位元組 
簡體中文                             GB2312                                    MBCS 多位元組 
繁體中文                             BIG5                                         MBCS 多位元組 
簡繁中文                             GBK                                         MBCS 多位元組 
中文、日文及朝鮮語         GB18030                                  MBCS 多位元組 
各國語言                             UNICODE,UCS                    DBCS 寬位元組 
三,編碼 
UTF-8:採用變長位元組 (1 ASCII, 2 希臘字母, 3 漢字, 4 平面符號) 表示,網路傳輸, 即使錯了一個位元組,不影響其他位元組,而雙位元組只要一個錯了,其他也錯了,具體如下: 
如果只有一個位元組則其最高二進位位為0;如果是多位元組,其第一個位元組從最高位開始,連續的二進位位值為1的個數決定了其編碼的位元組數,其餘各位元組均以10開頭。UTF-8最多可用到6個位元組。 
UTF-16:採用2位元組,Unicode中不同部分的字元都同樣基於現有的標準。這是為了便於轉換。從 0×0000到0×007F是ASCII字元,從0×0080到0×00FF是ISO-8859-1對ASCII的擴充。希臘字母表使用從0×0370到 0×03FF 的代碼,斯拉夫語使用從0×0400到0×04FF的代碼,美國使用從0×0530到0×058F的代碼,希伯來語使用從0×0590到0×05FF的代碼。中國、日本和韓國的表意字元(總稱為CJK)佔用了從0×3000到0×9FFF的代碼;由於0×00在c語言及作業系統檔案名稱等中有特殊意義,故很多情況下需要UTF-8編碼儲存文本,去掉這個0×00。舉例如下: 
UTF-16: 0×0080  = 0000 0000 1000 0000 
UTF-8:   0xC280 = 1100 0010 1000 0000 
UTF-32:採用4位元組。 
優缺點 
UTF-8、UTF-16和UTF-32都可以表示有效編碼空間 (U+000000-U+10FFFF) 內的所有Unicode字元。 
使用UTF-8編碼時ASCII字元只佔1個位元組,儲存效率比較高,適用於拉丁字元較多的場合以節省空間的。 
對於大多數非拉丁字元(如中文和日文)來說,UTF-16所需儲存空間最小,每個字元只佔2個位元組。 
Windows NT核心是Unicode(UTF-16),採用UTF-16編碼在調用系統API時無需轉換,處理速度也比較快。 
採用UTF-16和UTF-32會有Big Endian和Little Endian之分,而UTF-8則沒有位元組順序問題,所以UTF-8適合傳輸和通訊。 
UTF-32採用4位元組編碼,一方面處理速度比較快,但另一方面也浪費了大量空間,影響傳輸速度,因而很少使用。 
四,如何判斷字元集 
1,位元組序 
首先說一下位元組序對編碼的影響,位元組序分為Big Endian位元組序和Little Endian位元組序。不同的處理器可能不一樣。所以,傳輸時需要告訴處理器當時的編碼位元組序。對於前者而言,高位位元組存在低地址,低位元組存於高地址;後者相反。例如,0X03AB, 
Big Endian位元組序 
0000: 0 3 
0001: AB 
Little Endian位元組序是 
0000: AB 
0001: 0 3 
2,編碼識別 
UNICODE,根據前幾個位元組可以判斷UNICODE字元集的各種編碼,叫做Byte Order Mask方法BOM: 
UTF-8: EFBBBF (符合UTF-8格式,請看上面。但沒有含義在UCS即UNICODE中) 
UTF-16 Big Endian:FEFF (沒有含義在UCS-2中) 
UTF-16 Little Endian:FFFE (沒有含義在UCS-2中) 
UTF-32 Big Endian:0000FEFF (沒有含義在UCS-4中) 
UTF-32 Little Endian:FFFE0000 (沒有含義在UCS-4中) 
GB2312:高位元組和低位元組的第1位都是1。 
BIG5,GBK&GB18030:高位元組的第1位為1。作業系統有預設的編碼,常為GBK,可以下載別的並升級。
通過判斷高位元組的第1位從而知道是ASCII或者漢字編碼。

Karlson,2009-07-25 13:39:57

 

    1. class CChineseCode  
    2.  
    3. {  
    4.  
    5.   public:  
    6.  
    7.       static void UTF_8ToUnicode(wchar_t* pOut,char *pText);  // 把UTF-8轉換成Unicode  
    8.  
    9.       static void UnicodeToUTF_8(char* pOut,wchar_t* pText);  //Unicode 轉換成UTF-8  
    10.  
    11.       static void UnicodeToGB2312(char* pOut,wchar_t uData);  // 把Unicode 轉換成 GB2312    
    12.  
    13.       static void Gb2312ToUnicode(wchar_t* pOut,char *gbBuffer);// GB2312 轉換成 Unicode  
    14.  
    15.       static void GB2312ToUTF_8(string& pOut,char *pText, int pLen);//GB2312 轉為 UTF-8  
    16.  
    17.       static void UTF_8ToGB2312(string &pOut, char *pText, int pLen);//UTF-8 轉為 GB2312  
    18.  
    19. };  
    20.  
    21.  
    22.  
    23. 類實現  
    24.  
    25.  
    26.  
    27. void CChineseCode::UTF_8ToUnicode(wchar_t* pOut,char *pText)  
    28.  
    29. {  
    30.  
    31.    char* uchar = (char *)pOut;  
    32.  
    33.  
    34.  
    35.    uchar[1] = ((pText[0] & 0x0F) << 4) + ((pText[1] >> 2) & 0x0F);  
    36.  
    37.    uchar[0] = ((pText[1] & 0x03) << 6) + (pText[2] & 0x3F);  
    38.  
    39.  
    40.  
    41.    return;  
    42.  
    43. }  
    44.  
    45.  
    46.  
    47. void CChineseCode::UnicodeToUTF_8(char* pOut,wchar_t* pText)  
    48.  
    49. {  
    50.  
    51.    // 注意 WCHAR高低字的順序,低位元組在前,高位元組在後  
    52.  
    53.    char* pchar = (char *)pText;  
    54.  
    55.  
    56.  
    57.    pOut[0] = (0xE0 | ((pchar[1] & 0xF0) >> 4));  
    58.  
    59.    pOut[1] = (0x80 | ((pchar[1] & 0x0F) << 2)) + ((pchar[0] & 0xC0) >> 6);  
    60.  
    61.    pOut[2] = (0x80 | (pchar[0] & 0x3F));  
    62.  
    63.  
    64.  
    65.    return;  
    66.  
    67. }  
    68.  
    69.  
    70.  
    71. void CChineseCode::UnicodeToGB2312(char* pOut,wchar_t uData)  
    72.  
    73. {  
    74.  
    75.    WideCharToMultiByte(CP_ACP,NULL,&uData,1,pOut,sizeof(wchar_t),NULL,NULL);  
    76.  
    77.    return;  
    78.  
    79. }        
    80.  
    81.  
    82.  
    83. void CChineseCode::Gb2312ToUnicode(wchar_t* pOut,char *gbBuffer)  
    84.  
    85. {  
    86.  
    87.    ::MultiByteToWideChar(CP_ACP,MB_PRECOMPOSED,gbBuffer,2,pOut,1);  
    88.  
    89.    return ;  
    90.  
    91. }  
    92.  
    93.  
    94.  
    95. void CChineseCode::GB2312ToUTF_8(string& pOut,char *pText, int pLen)  
    96.  
    97. {  
    98.  
    99.    char buf[4];  
    100.  
    101.    int nLength = pLen* 3;  
    102.  
    103.    char* rst = new char[nLength];  
    104.  
    105.      
    106.  
    107.    memset(buf,0,4);  
    108.  
    109.    memset(rst,0,nLength);  
    110.  
    111.      
    112.  
    113.    int i = 0;  
    114.  
    115.    int j = 0;        
    116.  
    117.    while(i < pLen)  
    118.  
    119.    {  
    120.  
    121.            //如果是英文直接複製就可以  
    122.  
    123.            if( *(pText + i) >= 0)  
    124.  
    125.            {  
    126.  
    127.                    rst[j++] = pText[i++];  
    128.  
    129.            }  
    130.  
    131.            else  
    132.  
    133.            {  
    134.  
    135.                    wchar_t pbuffer;  
    136.  
    137.                    Gb2312ToUnicode(&pbuffer,pText+i);  
    138.  
    139.                      
    140.  
    141.                    UnicodeToUTF_8(buf,&pbuffer);  
    142.  
    143.                      
    144.  
    145.                    unsigned short int tmp = 0;  
    146.  
    147.                    tmp = rst[j] = buf[0];  
    148.  
    149.                    tmp = rst[j+1] = buf[1];  
    150.  
    151.                    tmp = rst[j+2] = buf[2];      
    152.  
    153.                      
    154.  
    155.                    j += 3;  
    156.  
    157.                    i += 2;  
    158.  
    159.            }  
    160.  
    161.    }  
    162.  
    163.    rst[j] = ‘‘;  
    164.  
    165.  
    166.  
    167.    //返回結果  
    168.  
    169.    pOut = rst;                
    170.  
    171.    delete []rst;     
    172.  
    173.      
    174.  
    175.    return;  
    176.  
    177. }  
    178.  
    179.  
    180.  
    181. void CChineseCode::UTF_8ToGB2312(string &pOut, char *pText, int pLen)  
    182.  
    183. {  
    184.  
    185.    char * newBuf = new char[pLen];  
    186.  
    187.    char Ctemp[4];  
    188.  
    189.    memset(Ctemp,0,4);  
    190.  
    191.  
    192.  
    193.    int i =0;  
    194.  
    195.    int j = 0;  
    196.  
    197.      
    198.  
    199.    while(i < pLen)  
    200.  
    201.    {  
    202.  
    203.        if(pText > 0)  
    204.  
    205.        {  
    206.  
    207.                newBuf[j++] = pText[i++];                          
    208.  
    209.        }  
    210.  
    211.        else                    
    212.  
    213.        {  
    214.  
    215.                WCHAR Wtemp;  
    216.  
    217.                UTF_8ToUnicode(&Wtemp,pText + i);        
    218.  
    219.                UnicodeToGB2312(Ctemp,Wtemp);                
    220.  
    221.                newBuf[j] = Ctemp[0];  
    222.  
    223.                newBuf[j + 1] = Ctemp[1];    
    224.  
    225.                i += 3;      
    226.  
    227.                j += 2;     
    228.  
    229.        }  
    230.  
    231.    }  
    232.  
    233.    newBuf[j] = ‘‘;    
    234.    pOut = newBuf;    
    235.    delete []newBuf;  
    236.    return;    
    237.  
    238. }

C++ 編碼轉換

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.