从UTF8格式向GB2312格式转换[C源码](转)

/***************************************************************************
* 文 件 名: UTF8_UCS2_GB2312.CPP
*
* 版 本 号: V1.0.0.1
*
* 作  者: lianxiuzhu
*
* 创建时间: 2008-05-22 11:48:13
*
* 文件描述: 从UTF8格式字符串转换成GB2312编码格式(经由UCS2编码)
*       UCS2编码是对双字节编码的统一描述,Unicode就是其中一种
* 假定条件: 用户输入到程序的UTF8字符串是符合UTF8基本规范
*       否则,程序执行的结果不可预料(包括产生异常)
***************************************************************************/

#include <stdio.h>
#include <stdlib.h>
#include <locale.h>

typedef char                         S8;  //有符号8位
typedef short                      S16;  //有符号16位
typedef int                          S32;  //有符号32位
typedef unsigned char         U8;  //无符号8位
typedef unsigned short      U16;  //无符号16位
typedef unsigned int          U32;  //无符号32位

/***************************************************************************
* 函数名称: RealVal
* 功能描述: 计算'0' - '9', 'a' - 'z', 'A - Z'分别对应的十进制数值
* 日  期: 2008-05-22 11:57:56
* 作  者: lianxiuzhu
* 参数说明: c - 十六进制字符
* 返 回 值: 对应的十进制数值
***************************************************************************/
U8 RealVal(S8 c)
{
  if(c >= '0' && c <= '9')
  {
    return (c - 48);
  }
  else if(c >= 'a' && c <= 'f')
  {
    return (c - 87);
  }
  else if(c >= 'A' && c <= 'F')
  {
    return (c - 55);
  }
  else
  {
    return 0;
  }
}

/***************************************************************************
* 函数名称: UTF8StringToStream
* 功能描述: 从UTF8格式的字符串转换成UTF8字节流数组(%E9%90-->0xE9,0x90)
* 日  期: 2008-05-22 13:34:01
* 作  者: lianxiuzhu
* 参数说明: szUTF8  - UTF8格式的字符串
*       binUTF8  - UTF8字节流数组
* 返 回 值: 转换到UTF8字节流数组中字节数
***************************************************************************/
U32 UTF8StringToStream(const S8* szUTF8, U8* binUTF8)
{
  U32 uCount = 0;
  S8* szTemp = (S8*)szUTF8;
  while(*szTemp != '\0')
  {
    if(*szTemp == '%')
    {
      binUTF8[uCount] = RealVal(*(szTemp + 1)) * 0x10 + RealVal(*(szTemp + 2));
      szTemp = szTemp + 3;
    }
    else if(*szTemp == '+')
    {
      binUTF8[uCount] = 0x20;
      szTemp = szTemp + 1;
    }
    else
    {
      binUTF8[uCount] = *szTemp;
      szTemp = szTemp + 1;
    }
    
    uCount = uCount + 1;
  }
  
  return uCount;
}

/***************************************************************************
* 函数名称: UTF8ToUCS2
* 功能描述: 转换UTF8格式到UCS2格式(UCS2是双字节编码,Unicode是其中一种)
* 日  期: 2008-05-22 13:36:56
* 作  者: lianxiuzhu
* 参数说明: binUTF8  - UTF8字节流数组
*       uCount  - UTF8字节流数组中的字节数
*       binUCS2  - UCS2字节流数组
* 返 回 值: 转换到UCS2字节流数组中的U16单元个数
***************************************************************************/
U32 UTF8ToUCS2(const U8* binUTF8, U32 uCount, U16* binUCS2)
{
  U32 uLength = 0;
  U8* szTemp = (U8*)binUTF8;
  while((U32)(szTemp - binUTF8) < uCount)
  {
    if(*szTemp <= 0x7F) //0xxxxxxx
    {
      binUCS2[uLength] = binUCS2[uLength] | (U16)(*szTemp & 0x7F);
      szTemp = szTemp + 1;
    }
    else if(*szTemp <= 0xDF) //110xxxxx 10xxxxxx
    {
      binUCS2[uLength] = binUCS2[uLength] | (U16)(*(szTemp + 1) & 0x3F);
      binUCS2[uLength] = binUCS2[uLength] | ((U16)(*(szTemp) & 0x1F) << 6);
      szTemp = szTemp + 2;
    }
    else if(*szTemp <= 0xEF) //1110xxxx 10xxxxxx 10xxxxxx
    {
      binUCS2[uLength] = binUCS2[uLength] | (U16)(*(szTemp + 2) & 0x3F);
      binUCS2[uLength] = binUCS2[uLength] | ((U16)(*(szTemp + 1) & 0x3F) << 6);
      binUCS2[uLength] = binUCS2[uLength] | ((U16)(*(szTemp) & 0x0F) << 12);
      szTemp = szTemp + 3;
    }
    else
    {
      return 0;
    }
    
    uLength = uLength + 1;
  }
  
  return uLength;
}

/*
* 测试用主程序:
* 功能:将一段UTF8格式的字符串,转化成GB2312格式输出
* 检验:如果您能看到屏幕输出“让我们永远铭记这一刻:2008年5月12日 14时28分”,成功!
*/
int main(int argc, char* argv[])
{
  S8* szUTF8 = "%E8%AE%A9%E6%88%91%E4%BB%AC%E6%B0%B8%E8%BF%9C%E9%93%AD%E8%AE%B0%E8%BF%99%E4%B8%80%E5%88%BB%EF%BC%9A2008%E5%B9%B45%E6%9C%8812%E6%97%A5+14%E6%97%B628%E5%88%86";
  U8 binUTF8[512] = {0};
  U32 uCount = UTF8StringToStream(szUTF8, binUTF8);
  if(uCount > 0)
  {
    U16 binUCS2[512] = {0};
    uCount = UTF8ToUCS2(binUTF8, uCount, binUCS2);
    if(uCount > 0)
    {
      S8 szGB2312[512] = {0};
      setlocale(LC_ALL, ".936");
      wcstombs(szGB2312, (wchar_t*)binUCS2, 512);
      printf("%s\n", szGB2312);
    }
  }
  
  return uCount;
}

posted @ 2009-10-20 08:49  木瓜脑袋  阅读(3548)  评论(0编辑  收藏  举报