utf-8与gbk互转

来源:互联网 发布:linux ps和netstat 编辑:程序博客网 时间:2024/06/05 17:12

UTF-8

UTF-8UCS字符集的另一种编码方式,UTF-16的每个单元是两个字节(16位),而UTF-8的每个单元是一个字节(8位)。UTF-16中用一个或两个双字节表示一个字符,UTF-8中用一个或几个单字节表示一个字符。

可以认为UTF-8编码是根据一定规律从UCS-2转换得到的,从UCS-2UTF-8之间有以下转换关系:

UCS-2 UTF-8

U+0000 - U+007F 0xxxxxxx

U+0080 - U+07FF 110xxxxx 10xxxxxx

U+0800 - U+FFFF 1110xxxx 10xxxxxx 10xxxxxx

例如“啊”字的UCS-2编码是0x554A,对应的二进制是0101 0101 0100 1010,转成UTF-8编码之后的二进制是1110 0101 10 010101 10 001010,对应的十六进制是0xE5958A


#include<stdio.h>
#include<string.h>
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);  //高四位填入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(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 low = *pInput;  
            if ((low & 0xC0) != 0x80)  //检查是否为合法的UTF8字符表示  
            {  
                return -1; //如果不是则报错  
            }  
  
            *pOutput = (high << 6) + (low & 0x3F);  
            pOutput++;  
            *pOutput = (high >> 2) & 0x07;  
        }  
        else if (((*pInput) & 0xF0) == 0xE0) //处理三字节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 s[5];  
    char* utf8Str =s;
    memset(utf8Str,0,5);  
   
    int num = UnicodeToUtf8(unicodeStr,utf8Str);  
  
    unsigned char* p = (unsigned char*)utf8Str;
    int i=0;     
    for(i = 0; i < num; i++)  
    {  
        printf("%0x", *p);  
        p++;  
    }//输出e68891  
    printf("\n");  
   
    //2、utf8转unicode  
    char utf8Str1[4] = {0xe6, 0x88, 0x91, 0x00};   
    char ss[8];  
    char* unicodeStr1 = ss;
    memset(unicodeStr1,0,8);  
    int num1 = Utf8ToUnicode(utf8Str1, unicodeStr1);  
    if (num1 == -1)  
    {  
      printf("Error!\n");  
    }  
    else  
    {  
           unsigned char* p = (unsigned char*)unicodeStr1;  
           int i1=0;
      for(i1 = 0; i1 < num1; i1++)  
      {  
          printf("%0x", *p);  
          p++;  
      }//输出1162  
    printf("\n");  
    }  
   
  
    return 0;  
}   

测试如下:
[root@libmaster bianma]# ./a.out 
e68891
1162









原创粉丝点击