UTF-8, Unicode, GB2312格式串转换之C语言版

UTF-8,Unicode,GB2312编码转换(C语言) UTF-8,Unicode,GB2312编码转换(C语言) 最近在做MQTT客户端的时候,遇到需要将输入的GB2312中文转换为UTF8的问题,这边做一个整理。 UTF-8转GB2312 /*! * \brief Gb2312至UTF8 转换函数 * * \details Gb2312 -> Unicode -> UTF8 * * \param const ch... 阅读详情

      (申明:此文章属于原创,若转载请表明作者和原处链接 )      
      /*      author:   wu.jian   (吴剑)      English name: Sword
      /*      date:      2007-12-13
      /*      purpose:   知识共享

      这几天工作上碰到了UTF-8转GB2312的问题,而且是在嵌入式的环境下,没有API可用,查了很多网上的资料,大多调用VC或者linux下自带的接口。在这里我将这两天的工作做个总结。
      总的来说分为两大步(这里就不介绍基础知识了):

      一、UTF8 -> Unicode
      由于UTF8和Unicode存在着联系,所以不需要任何库就可以直接进行转换。首先要看懂UTF8的编码格式:
      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就代表后面几个字节是属于一起的。如果要解析一长串UTF8格式的字符串,这点就很有用了。下面这个函数就是判断前面几个1的(这里有define APP_PRINT printf,这样当release的时候将这个宏定义为空就行了,不需要一个一个去改,又方便重新调试):
      int GetUtf8ByteNumForWord(u8 firstCh)
      {
          u8 temp = 0x80;
          int num = 0;
 
          while (temp & firstCh)
          {
                num++;
                 temp = (temp >> 1);
           }

       APP_PRINT("the num is: %d", num);
        return num;
      }
      利用这个函数可以得到字符串中那几个字节是一起的。因为UTF8最大只有6个字节,所以就根据返回值来处理这里我只处理了3个字节和1个字节的UTF8的编码,因为一般来说中文在UTF8中是3个字节。

//将len个字节的UTF8格式的转换成GB2312格式存放在temp预先申请好的缓冲区中
void Utf8ToGb2312(const char* utf8, int len, char *temp)
{
       APP_PRINT("utf8->unicode: \n");
       APP_PRINT("utf8: [");
       for (int k = 0; k < len; k++)
       {
              APP_PRINT("%02x ", utf8[k]);
       }
       APP_PRINT("]\n");
 
       int byteCount = 0;
       int i = 0;
       int j = 0;

       u16 unicodeKey = 0;
       u16 gbKey = 0;


      //循环解析
       while (i < len)
       {   
        switch(GetUtf8ByteNumForWord((u8)utf8[i]))
        {
          case 0:
                temp[j] = utf8[i];
                byteCount = 1;
          break;

          case 2:
          temp[j] = utf8[i];
          temp[j + 1] = utf8[i + 1];
          byteCount = 2;
          break;

         case 3:
                 //这里就开始进行UTF8->Unicode
                 temp[j + 1] = ((utf8[i] & 0x0F) << 4) | ((utf8[i + 1] >> 2) & 0x0F);
                 temp[j] = ((utf8[i + 1] & 0x03) << 6) + (utf8[i + 2] & 0x3F);

                //取得Unicode的值
                 memcpy(&unicodeKey, (temp + j), 2);
                 APP_PRINT("unicode key is: 0x%04X\n", unicodeKey);

                  //根据这个值查表取得对应的GB2312的值
                gbKey = SearchCodeTable(unicodeKey);
                APP_PRINT("gb2312 key is: 0x%04X\n", gbKey);
    
                if (gbKey != 0)
                {
                       //here change the byte
                        //不为0表示搜索到,将高低两个字节调换调成我要的形式
                       gbKey = (gbKey >> 8) | (gbKey << 8);
                       APP_PRINT("after changing, gb2312 key is: 0x%04X\n", gbKey);
                       memcpy((temp + j), &gbKey, 2);
                  }

                byteCount = 3;
          break;

          case 4:
          byteCount = 4;
          break;
         case 5:
          byteCount = 5;
          break;
         case 6:
          byteCount = 6;
          break;
    
         default:
          APP_PRINT("the len is more than 6\n");
          break;    
        }

        i += byteCount;
        if (byteCount == 1)
        {
               j++;
        }
        else
        {
               j += 2;
        }
  
       }
       APP_PRINT("utf8: [");
       for (k = 0; k < j; k++)
       {
              APP_PRINT("%02x ", temp[k]);
       }
       APP_PRINT("]\n");
}

      二、下面主要谈谈利用查表法来进行Unicode->GB2312的转换,首先下载码表,一般码表都是将GB2312的放在前面,Unicode放在后面,这样对于我们来说不方便使用,所以我转换了下,将Unicode放在前面,而且按照从小到大排好序。(这里只需要考虑都为两个字节的情况,因为前面的UTF8->Unicode并没有将单字节的ASCII转换成Unicode)
            (1)做表:(可以到这里下载:http://blog.91bs.com/?action=show&id=20,这里谢谢渣渣的猪窝)
            这个是原来的样子:
            0x8140 0x4E02 #CJK UNIFIED IDEOGRAPH
            0x8141 0x4E04 #CJK UNIFIED IDEOGRAPH
            0x8142 0x4E05 #CJK UNIFIED IDEOGRAPH
            先弄成(这个可以写个小程序来做,我就是在VC上做的,如果需要可以联系我):
            { 0x4E02 ,0x8140 }, //CJK UNIFIED IDEOGRAPH
            { 0x4E04 ,0x8141 }, //CJK UNIFIED IDEOGRAPH
            { 0x4E05 ,0x8142 }, //CJK UNIFIED IDEOGRAPH
            这样就可以把这些放在.h文件中了,下面是我的定义:
            typedef struct unicode_gb
            {
                   unsigned short unicode;
                   unsigned short gb;
            } UNICODE_GB;

            UNICODE_GB code_table[] = 
            {
                  { 0x4E02, 0x8140 },   //CJK UNIFIED IDEOGRAPH
                  { 0x4E04, 0x8141 },  //CJK UNIFIED IDEOGRAPH
                  { 0x4E05, 0x8142 },  //CJK UNIFIED IDEOGRAPH
                  。。。。。。省略

            下面这一步也很简单,在VC中用冒泡排序法,对这个数组按照unicode值进行排序,如果需要可以联系我,把最终结果打印出来,在cmd下运行name > 1.txt就输出到文件,这样就有了一个按照unicode排好序的unicode->gb2312码表。

   int main(int argc, char *argv[])
{

    int num = 0;
    UNICODE_GB temp;
    int i = 0;
    int j = 0;

    num = sizeof(code_table) / sizeof(UNICODE_GB);

    printf("struct size: %d | total size: %d | num is: %d \n", 
    sizeof(UNICODE_GB), sizeof(code_table), num);

    for (i = 0; i < num; i++)
    {
        for (j = 1; j < num - i; j++)
        {
            if (code_table[j - 1].unicode > code_table[j].unicode)
            {
                temp.unicode = code_table[j - 1].unicode;
                temp.gb = code_table[j - 1].gb;
                code_table[j - 1].unicode = code_table[j].unicode;
                code_table[j - 1].gb = code_table[j].gb;
                code_table[j].unicode = temp.unicode;
                code_table[j].gb = temp.gb;
            }
        }
    }

    printf("here is the code table sorted by unicode\n\n");

    for (i = 0; i < num; i++)
    {
        printf("{\t0x%04X,\t0x%04X\t},\t\n", code_table[i].unicode, code_table[i].gb);
     }

       printf("\n\n print over!\n");

   //以下注释掉的其实就是我用来对原来的码表添加,{,}等用的
   /*
    char buff[100];
    char buff_1[100]; 
 
    FILE* fp = NULL;
    FILE *fp_1 = NULL;

    memset(buff, 0, 100);
    memset(buff_1, 0, 100);
 
    fp = fopen("table.txt", "rw");
    fp_1 = fopen("table_1.txt", "a+");

    if ((fp == NULL) || (fp_1 == NULL))
    {
        printf("open file error!\n");
        return 1;
    }

    while (fgets(buff, 100, fp) != NULL)
    {
        buff[8] = ',';

        fputs(buff, fp_1);
    }
 */

    return 0;
}

      最后就是搜索算法了,前面已经排好序了,现在我们把排好序的码表放在我们真正需要的.h文件中。大家应该猜我用什么算法搜索了吧,二分法。

#define CODE_TABLE_SIZE 21791
//这个表是死的,所以就直接用宏表示长度,不用每次都用size,不过这样可能对移植性不好。
u16 SearchCodeTable(u16 unicodeKey)
{
    int first = 0;
    int end = CODE_TABLE_SIZE - 1;
    int mid = 0;

    while (first <= end)
    {
        mid = (first + end) / 2;

        if (code_table[mid].unicode == unicodeKey)
        {
            return code_table[mid].gb;
        }
        else if (code_table[mid].unicode > unicodeKey)
        {
            end = mid - 1;
        }
        else 
        {
            first = mid + 1;
        }
    }
    return 0;
}
      到此,已经能够将UTF8串转换成GB2312了。是一长串哦,而不是单个汉字的编码转换。

C语言实现GB2312与UNICODE互转(char * 与 wchar_t* 互转) 众所周知,GB2312与UNICODE互转,需要查“表”转换,那么关键就是怎么制作这个“表”了。 UNICODE码从0X4E00开始,到0X9FA0就可以了,另外还有几个,不那么常用,就可以不用添加了,可以先把这些打到一个文件里,并存储为数组形式, unsigned short uniChar[] = {0X4E00.....0X9FA0}; 然后把这个文件改成.h的,包含到工程里来 阅读详情

相关推荐

GB2312于Unicode互转C语言程序(完整VS2010工程)

GB2312于Unicode互转C语言程序(完整VS2010工程) 能够直接使用。

免费AI视频生成全流程:通义千问+Seedance 2.5+Grok实战指南

AI视频生成正在成为内容创作的重要方式,但高昂的API费用常让个人创作者望而却步。实际上,通过合理组合云端免费工具,也能搭建一条完整的视频生产链路:利用大模型生成脚本,用视频生成模型将文本渲染成画面,再借助多模态模型进行一致性校验。这种“文本+视频+多模态”的协作模式,将复杂的生成任务解耦为可独立调用的模块,既降低了本地硬件要求,也为批量内容验证提供了低成本方案。该流程适用于短视频素材快速产出、产品Demo验证以及AI应用集成等场景,核心在于打通免费账号、API调用与批量任务调度。本文以通义千问、Seeda

weixin_29044157的博客 386

Unicode字符与GB2312的相互转换

<br />使用JDK中的native2ascii.exe工具。(以下以GB2312编码为例)<br />1.将用GB2312编码的汉字转换成相应的Unicode编码:<br />比如有一个用GB2312编码的文件(a.txt或a.properties等等)里面写有汉字“我爱你就像老鼠爱大米”编译之后便得到"/u6211/u7231/u4f60/u5c31/u50cf/u8001/u9f20/u7231/u5927/u7c73/u3002"的Unicode编码。<br />转换方法为:在cmd的doc窗口下

feng200711021053的专栏 4172

Unity序列帧动画输出全攻略:Recorder+Timeline实战与透明通道处理

序列帧动画是游戏开发、影视动画和UI动效中的基础技术,指将连续动作分解为一系列静态图像并按序播放,形成动态视觉效果。其原理是通过时间轴精确控制每一帧的内容与时机,实现动画的逐帧呈现。在实时渲染领域,序列帧输出技术价值显著,它能够将动态内容高质量地转换为静态图像序列,便于跨平台复用、后期合成与资源分发。应用场景广泛,包括角色动画导出、技能特效制作、宣传片素材生成等。本文聚焦Unity引擎,深入解析如何利用Recorder与Timeline工具链,高效输出带Alpha透明通道的PNG序列帧,并重点攻克透明通道处

weixin_31556767的博客 328

SLUB DEBUG 检测slab 内存泄漏

文章介绍如何定位linux 内核中slab 内存泄漏。

一叶知秋的博客 1491

utf8转gb2312 c语言,UTF-8, Unicode, GB2312格式串转换之C语言版

(申明:此文章属于原创,若转载请表明作者和原处链接 )/*author:wu.jian(吴剑)English name: Sword/*date:2007-12-13/*purpose:知识共享这几天工作上碰到了UTF-8转GB2312的问题,而且是在嵌入式的环境下,没有API可用,查了很多网上的资料,大多调用VC或者l...

weixin_35414887的博客 2344

【CarMaker实战指南】从零构建环形测试场景与车辆连续仿真

本文详细介绍了如何使用CarMaker软件从零构建环形测试场景与实现车辆连续仿真。通过分步指导搭建闭环道路、连接交叉路口、规划车辆轨迹等核心操作,帮助用户掌握CarMaker的基础应用技巧,并提供了常见问题排查与进阶优化建议,适用于车辆耐久性测试和自动驾驶算法验证等场景。

weixin_29274969的博客 235

UTF-8, Unicode, GB2312格式串转换之C语言版---转

UTF-8, Unicode, GB2312格式串转换之C语言版      (申明:此文章属于原创,若转载请表明作者和原处链接 )            /*      author:   wu.jian   (吴剑)      English name: Sword      /*      date:      2007-12-13      /*      purpose:   知识共享      这几天工作上碰到了UTF-8转GB2312的问题,而且是在嵌入式的环境下,没有API可用,查了很多网上的

huazi0072009的专栏 1021

Spring AI Alibaba Graph进阶:如何用图算法优化你的推荐系统?

本文深入探讨了如何利用Spring AI Alibaba Graph的图算法优化推荐系统。通过分析用户行为数据的网络化特征,结合加权随机游走和社区发现算法,显著提升推荐精准度和用户点击率。文章还分享了混合推荐架构设计、性能优化技巧及生产环境中的实战经验,为开发者提供了一套完整的图算法推荐解决方案。

weixin_33738555的博客 128

从零开始:使用Python实现基于深度强化学习的柔性车间调度系统

本文详细介绍了如何使用Python和深度强化学习(DRL)构建柔性车间调度系统,特别关注图神经网络(GNN)与近端策略优化(PPO)算法的结合应用。通过实战指南,读者将学习从环境准备、异构图构建到PPO算法实现的全流程,最终实现生产效率的显著提升。

weixin_29074295的博客 245

字符编码格式串转换之C语言版(UTF-8, Unicode, GB2312)

UTF-8, Unicode, GB2312格式串转换之C语言版       (申明:此文章属于原创,若转载请表明作者和原处链接 )             /*      author:   wu.jian   (吴剑)      English name: Sword       /*      date:      2007-12-13       /*      purpose:   知识共

蔡松豆的博客 1万+

高效批量转换Java接口为MCP服务:降低重复劳动的实战指南

高效批量转换Java接口为MCP服务:降低重复劳动的实战指南

专注于编程、AI、人工智能等多个领域内容研究和分析 726

汉字编码

汉字编码 一、汉字所占的字节数 对于一个字符串sizeof("请放手"),结果值是4。测试操作系统:Centos 6.4,硬件平台:Windows 7 32位 + VirtualBox 4.3.12。看来用sizeof()来计算汉字所占用的字节或空间是不准确的。 strlen("请放手"),返回值是9。 二、汉字编码问题 在使用libxml2输出的时候,出现了占用空间不一致的问题。 读出的汉字用...

weixin_30493401的博客 141

Qt + windows + Linux+QtInstallerFramework打包教程

本文介绍了使用Qt Installer Framework在Windows和Linux系统下打包Qt应用程序的完整教程。Windows部分详细说明了从下载安装框架、配置环境变量、生成release版本,到创建安装包目录结构和修改配置文件的完整流程。Linux部分则重点讲解了环境变量设置、桌面应用配置(.desktop文件)以及两种打包方案:一种使用linuxdeployqt生成AppImage文件,另一种采用类似Windows的安装包方式。教程提供了关键配置文件(config.xml、package.xml

Qt历险记,专注Qt技术,三年医疗设备研发经验,1年机器视觉研发经验,半年柔性传感研发经验。 517

霍尼韦尔SoftMaster使用说明

霍尼韦尔SoftMaster使用说明

关于文字编码

  源文件用不同的编码方式编写,会导致代码的执行结果不同。用UE编辑文档时,可以使用快捷键"Ctrl + H"查看文字的字符编码(可以设置显示什么编码,ACII码、GBK、BIG5、Unicode等)。   在编译程序时,可以指定字符集,查看帮助信息:man gcc, :/charset      -finput-charset=charset 表示源文件的编码方式, 默认以UTF-8来解...

weixin_33982670的博客 95

怀旧版电脑GBC模拟器

再现原版GBC掌机的界面,电脑运行连游戏界面都一样大小,很怀旧,很真实,(英文版)强烈推荐,很小的文件,很难才找到的。

上一篇: java 快速开发框架
下一篇: linux下C语言utf-8编码与gb2312转换代码---libiconv
zljjava
博客等级 码龄15年 155粉丝 15原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值