Linux下C语言GB2312转UTF8学习总结
来源:互联网 发布:vr眼镜淘宝购物视频 编辑:程序博客网 时间:2024/06/10 06:29
关于字符编码的介绍,请参考如下帖子,写的很通俗易懂,赞一个~
http://apps.hi.baidu.com/share/detail/50707690
http://blog.csdn.net/zplove003/article/details/7090877
一、方法总结
方法一:直接使用记事本打开源码文件,在文件—>另存为里面选择编码类型为UTF8,可以直接将源文件保存为UTF8格式文件。
优点:快速方便
缺点:整个C文件都会转化为UTF8编码,在source insight中的所有中文注释全部变为乱码,感觉还是有点不太合适。如果注释都是英文的大神,可以无视~
方法二:在linux下使用iconv命令进行转换
例子:iconv -f gb2312 -t utf-8 gb2312toutf8.c> utf8.c
优缺点同方法一
方法三:直接调用linux的API函数iconv来实现。这个函数不仅能实现GB2312到UTF8的转换,还支持其他不同的编码方式转换。
优点:可以将指定内容转换为UTF8,中文注释不会乱码
方法四:自己做一个编码转换表。通过查表的方式来实现。编码表不确定全不全,因GB2312和UTF8没有算法可以直接转换,所以猜测iconv库函数的实现内部应该也是有会一张这样的表,下次找一下看下~ 如果经常使用的话,编码表最好排序一下,使用二分法或其他查找算法来进行查找,提高效率。优点:可以将指定内容转换为UTF8,中文注释不会乱码
缺点:可能某些嵌入式系统上裁剪掉部分库函数,并不支持这个功能
二、测试代码
因编码表代码太长,所以编码表只取了几个字符做测试,比较全的编码表单独在另一篇中贴出来了,直接复制过来替换即可。另外,如果调用转换比较频繁的话,可以先排序一下,后续用二分法或者其他方法查找,效率会高一点。
http://blog.csdn.net/huangjiancald/article/details/49498129
方法三和方法四的测试代码如下:
#include <stdio.h>#include <netinet/in.h>#include <iconv.h>#include <string.h>#include <errno.h>/*********************数据结构*******************************/typedef struct GB2312ToUTF{ unsigned short GB2312_Code; unsigned short UTF16; unsigned char UTF8_Byte0; unsigned char UTF8_Byte1; unsigned char UTF8_Byte2;}T_GB2312ToUTF;/*********************全局变量*******************************/static T_GB2312ToUTF T_GB2312ToUTFArray[]={ {0xC2EB,0x7801,0xE7,0xA0,0x81}, //码 {0xC2CA,0x7387,0xE7,0x8E,0x87}, //率};/*********************函数申明*******************************/int Gb2312ToUTF8ByCodeTable(unsigned char *src, unsigned char *dst);int GetUtfInfo(unsigned short usGb2312Data,T_GB2312ToUTF *pOutUtf);int code_convert(const char *from_charset,const char *to_charset,char *inbuf,size_t inlen,char *outbuf,size_t outlen);int Gb2312ToUTF8BySysAPI(char *inbuf,size_t inlen,char *outbuf,size_t outlen);/********************************************************************函数名称: GetUtfInfo功能说明: 通过编码表,查到到对应的UTF信息输入参数:usGb2312Data: 输入的GB2312编码值 pOutUtf : 成功时返回对应的UTF信息,调用方保证 分配足够内存返回值:成功:返回0, 失败: -1********************************************************************/int GetUtfInfo(unsigned short usGb2312Data,T_GB2312ToUTF *pOutUtf){ int i=0; int iUtfCodeTableLength =0; if(pOutUtf ==NULL) { printf("int put parameter error! pOutUtf is NULL"); return -1; } //求出编码表的长度 iUtfCodeTableLength = sizeof(T_GB2312ToUTFArray)/sizeof(T_GB2312ToUTF); for(i=0;i<iUtfCodeTableLength;i++) { if(usGb2312Data==T_GB2312ToUTFArray[i].GB2312_Code) { memcpy(pOutUtf,&T_GB2312ToUTFArray[i],sizeof(T_GB2312ToUTF)); break; } } if(i==iUtfCodeTableLength) { printf("warning,not found utf info in table!usGb2312Data = %02x\n",usGb2312Data); return -1; } return 0;}/********************************************************************函数名称: Gb2312ToUTF8ByCodeTable功能说明: 通过编码表,将GB2312格式字符串转化为UTF8格式字符串输入参数:src:输入原数据指针,dst:输出的UTF数据指针, 调用方要保证dst缓存内容足够大返回值: 成功:返回UTF编码的长度; 失败:-1;********************************************************************/int Gb2312ToUTF8ByCodeTable(unsigned char *src, unsigned char *dst){ unsigned char *pInData =NULL; unsigned char *pOutData =NULL; int iResult =-1; int iUtfOutLength =0; int iUtfCodeTableLength =0; unsigned short usHostByteData =0; //代表主机字节序 T_GB2312ToUTF t_Gb2312ToUtfInfo; memset(&t_Gb2312ToUtfInfo,0,sizeof(T_GB2312ToUTF)); if(src==NULL||dst==NULL) { printf("input parameter error!"); return -1; } pInData = src; pOutData =dst; while(*pInData!='\0') { //printf("pInData=%02x,iUtfOutLength=%d!\n",(int)(*pInData),iUtfOutLength); /*低于128属于ascii编码相关的符号,保持不变*/ if(*pInData<0x80) { *pOutData = *pInData; pInData++; pOutData++; iUtfOutLength++; } else if(*pInData>0xa1) { /*使用UE观察输入的gb中文是大端模式,所以这里要转换一下*/ usHostByteData = ntohs(*(unsigned short *)pInData); //printf("Host Byte:%x\n",usHostByteData ); iResult=GetUtfInfo(usHostByteData,&t_Gb2312ToUtfInfo); if(0==iResult) { memcpy(pOutData,&(t_Gb2312ToUtfInfo.UTF8_Byte0),3); pInData+=2; pOutData+=3; iUtfOutLength+=3; } else { *pOutData = *pInData; pInData++; pOutData++; iUtfOutLength++; } } else { *pOutData = *pInData; pInData++; pOutData++; iUtfOutLength++; } } return iUtfOutLength;}/********************************************************************函数名称: code_convert功能说明: 通过编码表,将GB2312格式字符串转化为UTF8格式字符串输入参数:src:输入原数据指针,dst:输出的UTF数据指针, 调用方要保证dst缓存内容足够大返回值: 成功:返回UTF编码的长度; 失败:-1;********************************************************************/int code_convert(const char *from_charset,const char *to_charset,char *inbuf,size_t inlen,char *outbuf,size_t outlen) { iconv_t cd; int rc; char **pin = &inbuf; char **pout = &outbuf; cd = iconv_open(to_charset,from_charset); if (cd==0) { printf("iconv_open failed,errno=%s\n", strerror(errno)); return -1; } memset(outbuf,0,outlen); if (iconv(cd,pin,&inlen,pout,&outlen)==-1) { if(0!=cd) { iconv_close(cd); } printf("iconv failed,errno=%s\n", strerror(errno)); return -1; } iconv_close(cd); return 0; } /********************************************************************函数名称: Gb2312ToUTF8BySysAPI功能说明: 通过编码表,将GB2312格式字符串转化为UTF8格式字符串输入参数:src:输入原数据指针,dst:输出的UTF数据指针, 调用方要保证dst缓存内容足够大返回值: 成功:返回UTF编码的长度; 失败:-1;********************************************************************/int Gb2312ToUTF8BySysAPI(char *inbuf,size_t inlen,char *outbuf,size_t outlen){ return code_convert("gb2312","utf-8",inbuf,inlen,outbuf,outlen); }void main(){ int iGb2312CodeLength=0; int iUtfCodeLength=0; char Gb2312[128]="码率:12Mbps"; //char Gb2312[128]="1112Mbps"; char ucUtfCode[256]={0}; char *p =NULL; p=Gb2312; iGb2312CodeLength =strlen(p); Gb2312[iGb2312CodeLength]='\0'; printf("Gb2312 code:%s,input iGb2312CodeLength=%d\n", Gb2312,iGb2312CodeLength); /*通过查找构建的编码表来实现转换*/ printf("use code table!\n"); iUtfCodeLength= Gb2312ToUTF8ByCodeTable((unsigned char*)Gb2312,(unsigned char*)ucUtfCode); printf("GB2312-> UTF8:%s,output iUtfLength=%d\n", ucUtfCode,iUtfCodeLength); memset(ucUtfCode,0,sizeof(ucUtfCode)); /*通过调用api函数来实现转换*/ printf("use sys api!\n"); Gb2312ToUTF8BySysAPI(Gb2312,(size_t)iGb2312CodeLength,ucUtfCode,(size_t)sizeof(ucUtfCode)); printf("GB2312-> UTF8:%s,output iUtfLength=%d\n", ucUtfCode,iUtfCodeLength); printf("main excceed end!\n"); return;}
三、遇到的问题
在调用iconv函数时产生了异常错误EILSEQ,同时生成了core文件。后面检查发现是iconv函数的输入参数类型不对导致的,修改后正常~
ubuntu:~/code_test/GB2UTF8/src$ ./test
Gb2312 code:??:12Mbps, iGb2312CodeLength=11
use code table!
GB2312-> UTF8:码率:12Mbps, iUtfLength=13
use sys api!
iconv failed,errno=Invalid or incomplete multibyte or wide character
GB2312-> UTF8:码率:12Mbps, iUtfLength=13
main excceed end!
*** stack smashing detected ***: ./testterminated
Aborted (core dumped)
四、测试结果
修改后测试结果正常,如下:
ubuntu:~/code_test/GB2UTF8/src$ gcc gb2312toutf8.c -o test
ubuntu:~/code_test/GB2UTF8/src$ ./test
Gb2312 code:??:12Mbps,input iGb2312CodeLength=11
use code table!
GB2312-> UTF8:码率:12Mbps,output iUtfLength=13
use sys api!
GB2312-> UTF8:码率:12Mbps,output iUtfLength=13
main excceed end!
- Linux下C语言GB2312转UTF8学习总结
- (c语言)gb2312和utf8转换
- Linux下 GB2312和UTF8转换接口
- Linux下 GB2312和UTF8转换接口
- c语言下的gb2312和utf8及unicode之间的互相转换
- linux utf8转gb2312 声音播放脚本
- utf8 转 gb2312
- gb2312转utf8
- utf8转gb2312
- Gb2312转Utf8
- UTF8转GB2312
- 汉字转拼音c/c++源码,支持gb2312和utf8
- 从UTF8格式向GB2312格式转换[C源码](转)
- c语言utf8转unicod
- C# 编码转换 UTF8转GB2312 GB2312转UTF8
- C# 编码转换 UTF8转GB2312 GB2312转UTF8
- C# 编码转换 UTF8转GB2312 GB2312转UTF8
- C# 编码转换 UTF8转GB2312 GB2312转UTF8
- [Django数据库模型]理解Django里的MTV开发模式
- 想干掉互联网公司, 那你必需....
- Julia : Set or Array ?
- dubbo 学习(5) dubbo多协议和多注册中心
- 随记--做一个“懒惰”的程序员
- Linux下C语言GB2312转UTF8学习总结
- mapreduce序列化机制
- 第一篇博客,开始我的工程师道路了
- 产品运营:5种活动类型,如何运营
- 06-图2 Saving James Bond - Easy Version
- String,StringBuffer和StringBuilder的区别
- 29.Android 传感器
- LeetCode13:Roman to Integer
- 【跟我学apache-commons】【四】commons-io的使用