1. 程式人生 > >不依賴任何系統API,用c語言實現gbk/utf8/unicode編碼轉換

不依賴任何系統API,用c語言實現gbk/utf8/unicode編碼轉換

轉載地址:https://blog.csdn.net/bladeandmaster88/article/details/54837338

漢字'我'

Unicode編碼是0x6211       01100010 00010001

UTF8編碼是    0xe68891   11100110  10001000 100010001

n

Unicode符號範圍

(十六進位制)

UTF-8編碼方式

(二進位制)

1

2

3

0x00 - 0x7F

0x80 - 0x7FF

0x800 - 0xFFFF

                                                                            0zzzzzzz

                                                            110yyyyy 10zzzzzz

                                             1110xxxx 10yyyyyy  10zzzzzz

4

5

6

0x10000 - 0x1FFFFF

0x200000 - 0x3FFFFFF

0x4000000 - 0x7FFFFFFF

                              11110xxx 10xxxxxx 10xxxxxx 10xxxxxx

               111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx

1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx

 

 

 

 

 

 

一、Unicode轉utf8

‘我’的unicode編碼0x6211,二進位制為: 01000010 00010001

將二進位制形式分割成3段為0110 001000010001(分別是高4位、中間的6位、最後的低6位)

unicode轉utf8只需要這3段分別填入1110xxxx 10yyyyyy 10zzzzzz中的xxxx yyyyyy zzzzzz

得utf8編碼是0xe6889,二進位制為: 11100110 10001000 100010001

int UnicodeToUtf8(char *pInput, char *pOutput)
{
    int len = 0; //記錄轉換後的utf8字串的位元組數
    while (*pInput) {
        //處理一個unicode字元
        char low = *pInput;  //取出unicode字元的低8位
        pInput++;
        char high = *pInput;  //取出unicode字元的高8位
        int w=high<<8;
        unsigned wchar = (high<<8)+low;  //高8位和低8位組成一個unicode字元,加法運算級別高
        
        if (wchar <= 0x7F) //英文字元
        {
            pOutput[len] = (char)wchar;  //取wchar的低8位
            len++;
        } 
        else if (wchar >= 0x80 && wchar <= 0x7FF) //可以轉換成雙位元組pOutput字元
        {
            pOutput[len] = 0xc0 | ((wchar >> 6)&0x1f);  //取出unicode編碼低6位後的5位,填充到110yyyyy 10zzzzzz 的yyyyy中
            len++;    
            pOutput[len] = 0x80 | (wchar & 0x3f);  //取出unicode編碼的低6位,填充到110yyyyy 10zzzzzz 的zzzzzz中
            len++;
        }   
        else if (wchar >= 0x800 && wchar < 0xFFFF) //可以轉換成3個位元組的pOutput字元
        {
            pOutput[len] = 0xe0 | ((wchar >> 12)&0x0f)J;  //高四位填入1110xxxx 10yyyyyy 10zzzzzz中的xxxx
            len++;
            pOutput[len] = 0x80 | ((wchar >> 6) & 0x3f);  //中間6位填入1110xxxx 10yyyyyy 10zzzzzz中的yyyyyy
            len++;
            pOutput[len] = 0x80 | (wchar & 0x3f);  //低6位填入1110xxxx 10yyyyyy 10zzzzzz中的zzzzzz
            len++;
        }

        else //對於其他位元組數的unicode字元不進行處理
        {
            return -1;
        }
        pInput++;//處理下一個unicode字元
    }
    //utf8字串後面,有個\0
    pOutput[len] = 0;
    return len;
}

        

二、utf8轉unicode

  utf8二進位制形式為1110xxxx 10yyyyyy 10zzzzzz

'我'的utf8編碼0xe6889,二進位制為:11100110 10001000 100010001

分別提取裡面的xxxx yyyyyy zzzzzz,然後組合成xxxxyyyy yyzzzzzz,

xxxxyyyy就是unicode的高8位,yyzzzzzz就是unicode的低8位

/*
* 將utf8編碼轉換成Unicode (UCS-2LE) 編碼  低地址存低位位元組
* 引數:
*     char *pInput    輸入字串
*     char *pOutput   輸出字串
* 返回值: 轉換後的Unicode字串的位元組數,如果出錯則返回-1
*/
//utf8轉unicode
int Utf8ToUnicode(char *pInput, char *pOutput)
{
    int outputSize = 0;   //記錄轉換後的Unicode字串的位元組數
    while(*pInput) {
        if (*pInput > 0x00 && *pInput <= 0x7F) //處理單位元組UTF8字元(英文字母、數字)
        {
            *pOutput = *pInput;
            pOutput++;
            *pOutput = 0;   //小端法表示,在高地址填補0
        } 
        else if (((*pInput) & 0xE0) == 0xC0) //處理雙位元組UTF8位元組
        {
            char high = *pInput;
            pInput++;
            char middle = *pInput;
            pInput++;
            char low = *pInput;
            if (((middle & 0xC0) != 0x80) || ((low & 0xC0) != 0x80)) {
                return -1;
            }
            *pOutput = (middle << 6) + (low & 0x3F); //取出middle的低兩位與low的低6位,組合成unicode字元的低8位
            pOutput++;
            *pOutput = (high << 4) + (middle >> 2) & 0x0F); //取出high的低四位與middle的中間四位,組合成unicode字元的高8位
        } 
        else //對於其他位元組數的UTF8字元不進行處理
        {
            return -1;
        }
        pInput ++; //處理下一個utf8字元
        pOutput++;
        outputSize += 2;
}

//unicode字串後面,有兩個\0
*pOutput = 0;
pOutput++;
*pOutput = 0;
return outputSize;
//一個呼叫示例
int main(int argc, char **argv)
{
    //漢字'我'的UTF8編碼是0xe68891,Unicode的編碼是0x6211
    //1.unicode轉utf8
    char unicodeStr[3] = {0x11, 0x62, 0x00}; //'我'的unicode是0x6211,按低地址存低位位元組
    char *utf8Str = new char[5];
    memset(utf8Str, 0, 5);
    int num = UnicodeToUtf8(unicodeStr, utf8Str);

    unsigned char *p = (unsigned char *)utf8Str;
    for (int i=0; i<num; i++) {
        printf("%0x", *p);
        p++;
    }//輸出e68891
    printf("\n");
    delete utf8Str;

    //2.utf8轉unicode
    //char utf8Str[4] = {0xe6, 0x88, 0x91, 0x00};
    //char *unicodeStr = new char[8];
    //memset(unicodeStr, 0, 8);
    //int num = Utf8ToUnicode(utf8Str, unicodeStr);
    //if(num == -1) {
    //    printf("Error!\n");
    //}
    //else
    //{
    //    unsigned char *p = (unsigned char *)unicodeStr;
    //    for (int i=0; i<num; i++) {
    //        printf("%0x", *p);
    //        p++;
    //    }//輸出1162
    //    printf("\n");
    //}
    //delete unicodeStr;

    return 0;
}

三、gbk與unicode互轉

程式碼下載地址:c語言利用編碼轉換表實現gbk與unicode互轉

 

參照部落格:

http://blog.csdn.net/tge7618291/article/details/7599902
http://www.ithao123.cn/content-1832906.html