GBK和UTF8之间的转换 C语言

2024-05-24 04:18
文章标签 语言 转换 之间 gbk utf8

本文主要是介绍GBK和UTF8之间的转换 C语言,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

GBK和UTF8之间的转换可以使用MultiByteToWideChar和WideCharToMultiByte两个API,方法是先把它们转换为中间编码Unicode,再转换为对应的编码即可。



#include  < stdio.h >
#include 
< windows.h >

// GBK编码转换到UTF8编码
int  GBKToUTF8(unsigned  char   *  lpGBKStr,unsigned  char   *  lpUTF8Str, int  nUTF8StrLen)
{
    wchar_t 
*  lpUnicodeStr  =  NULL;
    
int  nRetLen  =   0 ;

    
if ( ! lpGBKStr)   // 如果GBK字符串为NULL则出错退出
         return   0 ;

    nRetLen 
=  ::MultiByteToWideChar(CP_ACP, 0 ,( char   * )lpGBKStr, - 1 ,NULL,NULL);   // 获取转换到Unicode编码后所需要的字符空间长度
    lpUnicodeStr  =   new  WCHAR[nRetLen  +   1 ];   // 为Unicode字符串空间
    nRetLen  =  ::MultiByteToWideChar(CP_ACP, 0 ,( char   * )lpGBKStr, - 1 ,lpUnicodeStr,nRetLen);   // 转换到Unicode编码
     if ( ! nRetLen)   // 转换失败则出错退出
         return   0 ;

    nRetLen 
=  ::WideCharToMultiByte(CP_UTF8, 0 ,lpUnicodeStr, - 1 ,NULL, 0 ,NULL,NULL);   // 获取转换到UTF8编码后所需要的字符空间长度
    
    
if ( ! lpUTF8Str)   // 输出缓冲区为空则返回转换后需要的空间大小
    {
        
if (lpUnicodeStr)
            delete []lpUnicodeStr;
        
return  nRetLen;
    }
    
    
if (nUTF8StrLen  <  nRetLen)   // 如果输出缓冲区长度不够则退出
    {
        
if (lpUnicodeStr)
            delete []lpUnicodeStr;
        
return   0 ;
    }

    nRetLen 
=  ::WideCharToMultiByte(CP_UTF8, 0 ,lpUnicodeStr, - 1 ,( char   * )lpUTF8Str,nUTF8StrLen,NULL,NULL);   // 转换到UTF8编码
    
    
if (lpUnicodeStr)
        delete []lpUnicodeStr;
    
    
return  nRetLen;
}

//  UTF8编码转换到GBK编码
int  UTF8ToGBK(unsigned  char   *  lpUTF8Str,unsigned  char   *  lpGBKStr, int  nGBKStrLen)
{
    wchar_t * lpUnicodeStr 
=  NULL;
    
int  nRetLen  =   0 ;

    
if ( ! lpUTF8Str)   // 如果UTF8字符串为NULL则出错退出
         return   0 ;

    nRetLen 
=  ::MultiByteToWideChar(CP_UTF8, 0 ,( char   * )lpUTF8Str, - 1 ,NULL,NULL);   // 获取转换到Unicode编码后所需要的字符空间长度
    lpUnicodeStr  =   new  WCHAR[nRetLen  +   1 ];   // 为Unicode字符串空间
    nRetLen  =  ::MultiByteToWideChar(CP_UTF8, 0 ,( char   * )lpUTF8Str, - 1 ,lpUnicodeStr,nRetLen);   // 转换到Unicode编码
     if ( ! nRetLen)   // 转换失败则出错退出
         return   0 ;

    nRetLen 
=  ::WideCharToMultiByte(CP_ACP, 0 ,lpUnicodeStr, - 1 ,NULL,NULL,NULL,NULL);   // 获取转换到GBK编码后所需要的字符空间长度
    
    
if ( ! lpGBKStr)   // 输出缓冲区为空则返回转换后需要的空间大小
    {
        
if (lpUnicodeStr)
            delete []lpUnicodeStr;
        
return  nRetLen;
    }
    
    
if (nGBKStrLen  <  nRetLen)   // 如果输出缓冲区长度不够则退出
    {
        
if (lpUnicodeStr)
            delete []lpUnicodeStr;
        
return   0 ;
    }

    nRetLen 
=  ::WideCharToMultiByte(CP_ACP, 0 ,lpUnicodeStr, - 1 ,( char   * )lpGBKStr,nRetLen,NULL,NULL);   // 转换到GBK编码
    
    
if (lpUnicodeStr)
        delete []lpUnicodeStr;
    
    
return  nRetLen;
}

// 使用这两个函数的例子
int  main()
{
    
char  cGBKStr[]  =   " 我是中国人! " ;
    
char   *  lpGBKStr  =  NULL;
    
char   *  lpUTF8Str  =  NULL;
    FILE 
*  fp  =  NULL;
    
int  nRetLen  =   0 ;

    nRetLen 
=  GBKToUTF8((unsigned  char   * )cGBKStr,NULL,NULL);
    printf(
" 转换后的字符串需要的空间长度为:%d  " ,nRetLen);
    lpUTF8Str 
=   new   char [nRetLen  +   1 ];
    nRetLen 
=  GBKToUTF8((unsigned  char   * )cGBKStr,(unsigned  char   * )lpUTF8Str,nRetLen);
    
if (nRetLen)
    {
        printf(
" GBKToUTF8转换成功! " );
    }
    
else
    {
        printf(
" GBKToUTF8转换失败! " );
        
goto  Ret0;
    }
    
    fp 
=  fopen( " C:\GBK转UTF8.txt " , " wb " );   // 保存到文本文件
    fwrite(lpUTF8Str,nRetLen, 1 ,fp);
    fclose(fp);
    
    getchar();  
// 先去打开那个文本文件看看,单击记事本的“文件”-“另存为”菜单,在对话框中看到编码框变为了“UTF-8”说明转换成功了

    nRetLen 
=  UTF8ToGBK((unsigned  char   * )lpUTF8Str,NULL,NULL);   // 再转回来
    printf( " 转换后的字符串需要的空间长度为:%d  " ,nRetLen);
    lpGBKStr 
=   new   char [nRetLen  +   1 ];
    nRetLen 
=  UTF8ToGBK((unsigned  char   * )lpUTF8Str,(unsigned  char   * )lpGBKStr,nRetLen);
    
if (nRetLen)
    {
        printf(
" UTF8ToGBK转换成功!  " );
    }
    
else
    {
        printf(
" UTF8ToGBK转换失败!  " );
        
goto  Ret0;
    }

    fp 
=  fopen( " C:\UTF8转GBK.txt " , " wb " );   // 保存到文本文件
    fwrite(lpGBKStr,nRetLen, 1 ,fp);
    fclose(fp);
    
    getchar();  
// 再去打开文本文件看看,发现编码框又变为了“ANSI”说明转换成功了

Ret0:
    
if (lpGBKStr)
        delete []lpGBKStr;
    
    
if (lpUTF8Str)
        delete []lpUTF8Str;
        
    
return   0 ;
}

 在网上看到的一些文章说,UTF8转换为GBK的时候会有问题,特别是当UTF8字符串中的汉字数为奇数时。关于这个问题我没有去验证过,而且我对UTF8和GB2312的编码还不是很熟悉,呵呵,等以后有空的时候再去了解一下编码吧。

这篇关于GBK和UTF8之间的转换 C语言的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/997343

相关文章

C语言中%zu的用法解读

《C语言中%zu的用法解读》size_t是无符号整数类型,用于表示对象大小或内存操作结果,%zu是C99标准中专为size_t设计的printf占位符,避免因类型不匹配导致错误,使用%u或%d可能引发... 目录size_t 类型与 %zu 占位符%zu 的用途替代占位符的风险兼容性说明其他相关占位符验证示

Python进行JSON和Excel文件转换处理指南

《Python进行JSON和Excel文件转换处理指南》在数据交换与系统集成中,JSON与Excel是两种极为常见的数据格式,本文将介绍如何使用Python实现将JSON转换为格式化的Excel文件,... 目录将 jsON 导入为格式化 Excel将 Excel 导出为结构化 JSON处理嵌套 JSON:

C语言进阶(预处理命令详解)

《C语言进阶(预处理命令详解)》文章讲解了宏定义规范、头文件包含方式及条件编译应用,强调带参宏需加括号避免计算错误,头文件应声明函数原型以便主函数调用,条件编译通过宏定义控制代码编译,适用于测试与模块... 目录1.宏定义1.1不带参宏1.2带参宏2.头文件的包含2.1头文件中的内容2.2工程结构3.条件编

Go语言并发之通知退出机制的实现

《Go语言并发之通知退出机制的实现》本文主要介绍了Go语言并发之通知退出机制的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧... 目录1、通知退出机制1.1 进程/main函数退出1.2 通过channel退出1.3 通过cont

Go语言编译环境设置教程

《Go语言编译环境设置教程》Go语言支持高并发(goroutine)、自动垃圾回收,编译为跨平台二进制文件,云原生兼容且社区活跃,开发便捷,内置测试与vet工具辅助检测错误,依赖模块化管理,提升开发效... 目录Go语言优势下载 Go  配置编译环境配置 GOPROXYIDE 设置(VS Code)一些基本

Kotlin Map映射转换问题小结

《KotlinMap映射转换问题小结》文章介绍了Kotlin集合转换的多种方法,包括map(一对一转换)、mapIndexed(带索引)、mapNotNull(过滤null)、mapKeys/map... 目录Kotlin 集合转换:map、mapIndexed、mapNotNull、mapKeys、map

深入理解Go语言中二维切片的使用

《深入理解Go语言中二维切片的使用》本文深入讲解了Go语言中二维切片的概念与应用,用于表示矩阵、表格等二维数据结构,文中通过示例代码介绍的非常详细,需要的朋友们下面随着小编来一起学习学习吧... 目录引言二维切片的基本概念定义创建二维切片二维切片的操作访问元素修改元素遍历二维切片二维切片的动态调整追加行动态

Javaee多线程之进程和线程之间的区别和联系(最新整理)

《Javaee多线程之进程和线程之间的区别和联系(最新整理)》进程是资源分配单位,线程是调度执行单位,共享资源更高效,创建线程五种方式:继承Thread、Runnable接口、匿名类、lambda,r... 目录进程和线程进程线程进程和线程的区别创建线程的五种写法继承Thread,重写run实现Runnab

Go语言中make和new的区别及说明

《Go语言中make和new的区别及说明》:本文主要介绍Go语言中make和new的区别及说明,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录1 概述2 new 函数2.1 功能2.2 语法2.3 初始化案例3 make 函数3.1 功能3.2 语法3.3 初始化

C# 比较两个list 之间元素差异的常用方法

《C#比较两个list之间元素差异的常用方法》:本文主要介绍C#比较两个list之间元素差异,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧... 目录1. 使用Except方法2. 使用Except的逆操作3. 使用LINQ的Join,GroupJoin