加载中…
个人资料
  • 博客等级:
  • 博客积分:
  • 博客访问:
  • 关注人气:
  • 获赠金笔:0支
  • 赠出金笔:0支
  • 荣誉徽章:
正文 字体大小:

Unicode,UTF8,GB2312,UCS2,GBK之间的转换

(2012-02-02 22:27:37)
标签:

it

Unicode,UTF8,GB2312,UCS2,GBK之间的转换

  

    平时用到的几种编码格式转换。平时用的不是很多。但是在做短信协议的时候,就经常遇到了。这段时间做短信平台接口,总结了几个,也不是很全。

//////////////////////////////////////////////////////////////////////////////

//把汉字格式化为%HH
int URLEncode(LPCTSTR pInBuf,LPTSTR szOut)
{
LPBYTE pInTmp,pOutTmp;
pInTmp = (LPBYTE)pInBuf;
pOutTmp = (LPBYTE)szOut;
while (*pInTmp){
if(isalnum(*pInTmp)){
   *pOutTmp++ = *pInTmp;
}else{
  
   if(isspace(*pInTmp)){
    *pOutTmp++ = '+';
   }else{    
    *pOutTmp++ = '%';    
    *pOutTmp++ = toHex(*pInTmp>>4);    
    *pOutTmp++ = toHex(*pInTmp&0xF);    
   }
}
pInTmp++;
}
*pOutTmp = '\0';
return (int)(pOutTmp-(LPBYTE)szOut);
}

///////////////////////////////////////////////////////////////////

// Unicode字符 转换成UTF-8编码
LPCTSTR UnicodeToUTF8Char(LPTSTR pOut,WCHAR wcText)
{
// 注意 WCHAR高低字的顺序,低字节在前,高字节在后
LPTSTR pchar = (LPTSTR)&wcText;
pOut[0] = (0xE0 | ((pchar[1] & 0xF0) >> 4));
pOut[1] = (0x80 | ((pchar[1] & 0x0F) << 2)) + ((pchar[0] & 0xC0) >> 6);
pOut[2] = (0x80 | (pchar[0] & 0x3F));
pOut[3] = '\0';
return pOut;
}


//GB2312字符串转为UTF-8编码
LPCTSTR GB2312ToUTF8(LPTSTR pUTF8Out,LPCTSTR pGB2312Input, int GB2312Len)
{
CHAR buf[4];  
LPCTSTR lpReturn,pGB2312Cursor,pGB2312InputEnd;
WCHAR wcBuffer;

lpReturn = (LPCTSTR)pUTF8Out;
pGB2312Cursor = (LPTSTR)pGB2312Input;
pGB2312InputEnd= pGB2312Cursor + GB2312Len;

while( pGB2312Cursor<pGB2312InputEnd ){
//如果ANSII直接复制就可以
if( *pGB2312Cursor>0 ){
   *pUTF8Out++ = *pGB2312Cursor++;  
}else{  
   ::MultiByteToWideChar(CP_ACP,MB_PRECOMPOSED,pGB2312Cursor,2,&wcBuffer,1);
   memcpy( pUTF8Out, UnicodeToUTF8Char(buf,wcBuffer), 3 );
   pGB2312Cursor += 2;
   pUTF8Out += 3;  
}
}
*pUTF8Out = '\0';
return lpReturn;
}


int UTF8ToGB(const char* str,char *out)
{
WCHAR *strSrc;
TCHAR *szRes;
int len;

//获得临时变量的大小
int i = MultiByteToWideChar(CP_UTF8, 0, str, -1, NULL, 0);
strSrc = new WCHAR[i+1];
MultiByteToWideChar(CP_UTF8, 0, str, -1, strSrc, i);

//获得临时变量的大小
i = WideCharToMultiByte(CP_ACP, 0, strSrc, -1, NULL, 0, NULL, NULL);
szRes = new TCHAR[i+1];
WideCharToMultiByte(CP_ACP, 0, strSrc, -1, szRes, i, NULL, NULL);

len = (i+1)*sizeof(CHAR);
memcpy(out,szRes,len);
out[len+1] ='\0';

delete []strSrc;
delete []szRes;

return len;
}


//GB2312字符串转为GB2312网页编码
LPCTSTR GB2312ToWebGB2312(LPTSTR pWebGB2312Out,LPCTSTR pGB2312Input, int GB2312Len)
{

LPCTSTR lpReturn,pGB2312Cursor,pGB2312InputEnd;
WCHAR wcBuffer;

lpReturn = (LPCTSTR)pWebGB2312Out;
pGB2312Cursor = (LPTSTR)pGB2312Input;
pGB2312InputEnd= pGB2312Cursor + GB2312Len;

while( pGB2312Cursor<pGB2312InputEnd ){
//如果ANSII直接复制就可以
if( *pGB2312Cursor>0 ){
   *pWebGB2312Out++ = *pGB2312Cursor++;  
}else{  
   ::MultiByteToWideChar(CP_ACP,MB_PRECOMPOSED,pGB2312Cursor,2,&wcBuffer,1);
   pWebGB2312Out += sprintf( pWebGB2312Out, "&#%d;", wcBuffer);
   pGB2312Cursor += 2;  
}
}
*pWebGB2312Out = '\0';
return lpReturn;
}


void UCS2toUTF8(unsigned short *ucs2, int count, char *utf8)
{
    unsigned short unicode;
    unsigned char bytes[4] = {0};
    int nbytes = 0;
    int i = 0, j = 0;
    int len=0;

    if((ucs2 != NULL) && (utf8 != NULL))
    {
        if(count == 0)
        {
            len = 0;
        }
        else
        {
   for (i=0; i<count; i++)
   {
    unicode = ucs2[i];
   
    if (unicode < 0x80)
    {
     nbytes = 1;
     bytes[0] = unicode;
    }
    else if (unicode < 0x800)
    {
     nbytes = 2;
     bytes[1] = (unicode & 0x3f) | 0x80;
                    bytes[0] = ((unicode << 2) & 0x1f00 | 0xc000) >> 8;
    }
    else
    {
     nbytes = 3;
     bytes[2] = (unicode & 0x3f) | 0x80;
     bytes[1] = ((unicode << 2) & 0x3f00 | 0x8000) >> 8;
                    bytes[0] = ((unicode << 4) & 0x0f0000 | 0xe00000) >> 16;
    }
   
    for (j=0; j<nbytes; j++)
    {
     utf8[len] = bytes[j];
     len++;
                }
            }
        }
       
        utf8[len] = '\0';
    }
}

 

///////////////////////////////////////////////////////////////////

//UCS2转换UTF8


///////////////////////////////////////////////////////////////////


///////////////////////////////////////////////////////////////////

//UTF8转换GB


///////////////////////////////////////////////////////////////////

 

http://blog.csdn.net/tanwei1002/article/details/4539266 

===================================================================================

 http://www.wangchao.net.cn/bbsdetail_34579.html
本文简单介绍UCS,UNICODE和UTF-8,并利用C语言实现了UTF-8与UCS2之间的互相转化。
  1.什么是UCS和ISO10646?
  国际标准ISO10646定义了通用字符集(Universal Character Set, UCS). UCS是所有其它字符集标准的一个超集,它保证也其它字符集双向兼容,即编码间相互转换不会丢失任何信息。UCS字符集U+0000到U+007F与US-ASCII是一致的。
  2.什么是UNICODE
  历史上, 有两个独立的, 创立单一字符集的尝试. 一个是国际标准化组织(ISO)的 ISO 10646 项目, 另一个是由(一开始大多是美国的)多语言软件制造商组成的协会组织的 Unicode 项目. 幸运的是, 1991年前后, 两个项目的参与者都认识到, 世界不需要两个不同的单一字符集. 它们合并双方的工作成果, 并为创立一个单一编码表而协同工作. 两个项目仍都存在并独立地公布各自的标准, 但 Unicode 协会和 ISO/IEC JTC1/SC2 都同意保持 Unicode 和 ISO 10646 标准的码表兼容, 并紧密地共同调整任何未来的扩展.
  3.什么是UTF-8(一种传送和存储格式)
  UCS和UNICODE为每个字符分配了一个对应的整数,但并没有明确说明其实现机制.故存在多种编码方式,其中以两个字节和四个字节来存储一个字符的方法分别叫UCS-2, UCS-4,要将一个ASCII文件转换成一个UCS-2文件只要在每个字节前加一个字节0X00,转换成UCS-4只要在每个字节前加三个0X00。
  而internet上大量的信息是以ASCII码存在的,如果都用两个字节来存储将浪费大量的资源,同时Unix和Linux下使用USC-2和USC-4会导致严重问题,于是出现了UTF-8(定义于ISO10646-1).

UTF-8(UTF-8 stands for Unicode Transformation Format-8. It is an octet (8-bit) lossless encoding of Unicode characters.)
  UNICODE(UCS)和UTF-8的对应关系。
  U-00000000 - U-0000007F: 0xxxxxxx
  U-00000080 - U-000007FF: 110xxxxx 10xxxxxx
  U-00000800 - U-0000FFFF: 1110xxxx 10xxxxxx 10xxxxxx
  U-00010000 - U-001FFFFF: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
  U-00200000 - U-03FFFFFF: 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
  U-04000000 - U-7FFFFFFF: 1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
  在多字节串中,第一个字节的开头‘1’的数目就是整个串中字节的数目.
  下面举UCS-2与UTF-8的对应关系,并利用C语言实现之间的互相转化。
  ------------------------------------------------------------------------------------------  | UCS2 | UTF-8 |
  |-----------------------------------------------------------------------------------------  | | code | 1st Byte | 2nd byte | 3rd Byte |
  |-----------------------------------------------------------------------------------------  | 000000000aaaaaaa | 0000 - 007F | 0aaaaaaa | | |
  |-----------------------------------------------------------------------------------------  | 00000bbbbbaaaaaa | 0080 - 07FF | 110bbbbb | 10aaaaaa | |
  |-----------------------------------------------------------------------------------------  | ccccbbbbbbaaaaaa | 0800 - FFFF | 1110cccc | 10bbbbbb | 10aaaaaa |
  |----------------------------------------------------------------------------------------- 

  在这儿我只实现了单个字符的转换,串的转换也是一样的道理。
  1,把一个UTF-8字符转换成一个UCS-2字符。
  如果转换成功返回1,如果UTF-8字符是一个unrecognized字符,则返回0,且存一个blackbox(U+22e0)到ucs2_code_ptr中。
  typedef unsigned short UINT16;
  typedef unsigned char UINT8;
  typedef unsigned char BOOL;
  #define TRURE (BOOL)(1)
  #define FALSE (BOOL)(0)
  BOOL UTF8toUCS2Code(const UINT8* utf8_code, UINT16* ucs2_code){
   UINT16 temp1, temp2;
   BOOL is_unrecognized = FALSE ;
   UINT16 * in = utf8_code;
   if(!utf8_code || !ucs2_code){
   return is_unrecognized;
   }
  
   if(0x00 == (*in & 0x80)){
  
   *ucs2_code= (UINT16)*in;
   is_unrecognized = TRUE;
   }
   else if(0xc0 == (*in & 0xe0) &&
   0x80 == (*(in + 1) & 0xc0)
   ){
  
   temp1 = (UINT16)(*in & 0x1f);
   temp1 <<= 6;
   temp1 |= (UINT16)(*(in + 1) & 0x3f);
   *ucs2_code = temp1;
   is_unrecognized = TRUE;
   }
   else if( 0xe0 == (*in & 0xf0) &&
   0x80 == (*(in +1) & 0xc0) &&
   0x80 == (*(in + 2) & 0xc0)
   ){
  
   temp1 = (UINT16)(*in &0x0f);
   temp1 <<= 12;
   temp2 = (UINT16)(*(in+1) & 0x3F);
   temp2 <<= 6;
   temp1 = temp1 | temp2 | (UINT16)(*(in+2) & 0x3F);
   *ucs2_code = temp1;
   is_unrecognized = TRUE;
   }
   else{
  
   *ucs2_code = 0x22e0;
   is_unrecognized = FALSE;
   }
   return is_unrecognized;
  }
  2,把一个UCS-2字符转换成UTF-8字符。函数返回转换成UTF-8的长度(字节1 -- 3),如果目标指针为空,返回0。
  UINT8 UCS2toUTF8Code(UINT16 ucs2_code, UINT8* utf8_code){
   int length = 0;
   UINT8* out = utf8_code;
   if(!utf8_code){
   return length;
   }
   if(0x0080 > ucs2_code){
  
   *out = (UINT8)ucs2_code;
   length++;
   }
   else if(0x0800 > ucs2_code){
  
   *out = ((UINT8)(ucs2_code >> 6)) | 0xc0;
   *(out+1) = ((UINT8)(ucs2_code & 0x003F)) | 0x80;
   length += 2;
   }
   else{
  
   *out = ((UINT8)(ucs2_code >> 12)) | 0xE0;
   *(out+1) = ((UINT8)((ucs2_code & 0x0FC0)>> 6)) | 0x80;
   *(out+2) = ((UINT8)(ucs2_code & 0x003F)) | 0x80;
   length += 3;
   }
   return length;
  }
 

=======================================================================================

UCS2转化为十六进制字符串问题

 

先看代码:
int EncodeUCS2(unsigned char *SourceBuf,unsigned char *DestBuf)
{
    int len,i,j=0;
    wchar_t wcbuf[255]; 
    unsigned char ucs2str[1024];
   
    setlocale(LC_ALL,"");
    len = mbstowcs(wcbuf,(char*)SourceBuf,255); 
    for (i=0;i<len;i++)
    {
        DestBuf[j++] = wcbuf[i]>>8;     
        DestBuf[j++] = wcbuf[i]&0xff;   
    }
    //
    printf("j=%d\n",j);
   
    printf("\n");
    //
    return len*2;
}
这是一个linuxC++程序,问题出在注释的部分,当前DestBuf是一个乱码(USC2格式),我想把它转化成16进制,然后赋值给DestBuf,我现在知道怎么把乱码按16进制格式打印出来,但不会给DestBuf赋值,老是报错(就是注释部分),打印方法这样的 
for(i=0;i<len;i++ ) printf("X",DestBuf[i]);
 
给个转化例子:
汉字:
没事,不要回 abc
最终转化结果:(当然这个值是要赋在DestBuf里的)
0891683108100005F011FF0B815118802053F10008A7146CA14E8BFF0C4E0D898156DE0020006100620063

问题补充:

1楼你好,你刚才说的地方是已经赋值了,但是得到的是UCS2编码(2个字节的Unicode编码),举个例子说
DestBuf数组中每一个元素都是两个字节表示的,直接打印出来就是乱码,我想把这个值转成16进制表示的,也可以换个变量表示,数组中每个元素只有一个字节
你不是已经给DestBuf赋值了吗?
 for (i=0;i<len;i++)
    {
        DestBuf[j++] = wcbuf[i]>>8;     
        DestBuf[j++] = wcbuf[i]&0xff;   
    }
有问题吗? 


你是不是要这个结果:

   char s[1000];
   for(int k = 0; k < len; k ++)
   {
      sprintf(&s[2*k],"X",DestBuf[k]);
   } 
   s[2*k] ='\0';

0

阅读 收藏 喜欢 打印举报/Report
  

新浪BLOG意见反馈留言板 欢迎批评指正

新浪简介 | About Sina | 广告服务 | 联系我们 | 招聘信息 | 网站律师 | SINA English | 产品答疑

新浪公司 版权所有