linux下c语言利用iconv函数实现utf-8转unicode
iconv是linux下的编码转换的工具,它提供命令行和函数接口支持
1.命令行
man手册iconv命令用法如下:
iconv -f encoding -t encoding inputfile
有如下选项可用:
输入/输出格式规范:-f, --from-code=名称 原始文本编码 -t, --to-code=名称 输出编码
信息:
-l, --list 列举所有已知的字符集
输出控制:
-c 从输出中忽略无效的字符 -o, --output=FILE 输出文件 -s, --silent 关闭警告 --verbose 打印进度信息
示例:下面的命令是将一个utf8编码的文件转换为一个unicode编码的文件
iconv -f utf-8 -t unicode utf8file.txt> unicodefile.txt
2.函数接口
iconv函数族的头文件是iconv.h,使用前需包含之。
#include <iconv.h>
iconv函数族有三个函数,原型如下:
iconv_t iconv_open(const char *tocode, const char *fromcode);
此函数说明将要进行哪两种编码的转换,tocode是目标编码,fromcode是原编码,该函数返回一个转换句柄,供以下两个函数使用。
size_t iconv(iconv_t cd,char **inbuf,size_t *inbytesleft,char **outbuf,size_t *outbytesleft);
此函数从inbuf中读取字符,转换后输出到outbuf中,inbytesleft用以记录还未转换的字符数,outbytesleft用以记录输出缓冲的剩余空间。
注意:inbuf和outbuf都必须是有存储空间的不能定义为常量,如:char *inbuf = "abc" 或者是char *outbuf = "123"这样定义都是错误的。另外inbuf,inbytesleft,outbuf,outbytesleft这几个参数在使用过程中都会改变,最好是先保存一下原值,然后再使用
int iconv_close(iconv_t cd);
此函数用于关闭转换句柄,释放资源。
基本使用举例:
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <iconv.h> int main(int argc, char **argv) { /* 目的编码, TRANSLIT:遇到无法转换的字符就找相近字符替换 * IGNORE :遇到无法转换字符跳过*/ //char *encTo = "UNICODE//TRANSLIT"; char *encTo = "UNICODE//IGNORE"; /* 源编码 */ char *encFrom = "UTF-8"; /* 获得转换句柄 *@param encTo 目标编码方式 *@param encFrom 源编码方式 * * */ iconv_t cd = iconv_open (encTo, encFrom); if (cd == (iconv_t)-1) { perror ("iconv_open"); } /* 需要转换的字符串 */ char inbuf[1024] = "abcdef哈哈哈哈行"; size_t srclen = strlen (inbuf); /* 打印需要转换的字符串的长度 */ printf("srclen=%d\n", srclen); /* 存放转换后的字符串 */ size_t outlen = 1024; char outbuf[outlen]; memset (outbuf, 0, outlen); /* 由于iconv()函数会修改指针,所以要保存源指针 */ char *srcstart = inbuf; char *tempoutbuf = outbuf; /* 进行转换 *@param cd iconv_open()产生的句柄 *@param srcstart 需要转换的字符串 *@param srclen 存放还有多少字符没有转换 *@param tempoutbuf 存放转换后的字符串 *@param outlen 存放转换后,tempoutbuf剩余的空间 * * */ size_t ret = iconv (cd, &srcstart, &srclen, &tempoutbuf, &outlen); if (ret == -1) { perror ("iconv"); } printf ("inbuf=%s, srclen=%d, outbuf=%s, outlen=%d\n", inbuf, srclen, outbuf, outlen); int i = 0; for (i=0; i<strlen(outbuf); i++) { printf("%x\n", outbuf[i]); } /* 关闭句柄 */ iconv_close (cd); return 0; }
下面做了一下函数的封装:
/* * ===================================================================================== * * Filename: iconv.c * * Description: j * * Version: 1.0 * Created: 08/05/2015 05:51:47 PM * Revision: none * Compiler: gcc * * Author: YOUR NAME (), * Organization: * * ===================================================================================== */ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <stdbool.h> #include <iconv.h> bool unicode_to_utf8 (char *inbuf, size_t *inlen, char *outbuf, size_t *outlen) { /* 目的编码, TRANSLIT:遇到无法转换的字符就找相近字符替换 * IGNORE :遇到无法转换字符跳过*/ char *encTo = "UTF-8//IGNORE";
/* 源编码 */ char *encFrom = "UNICODE"; /* 获得转换句柄 *@param encTo 目标编码方式 *@param encFrom 源编码方式 * * */ iconv_t cd = iconv_open (encTo, encFrom); if (cd == (iconv_t)-1) { perror ("iconv_open"); } /* 需要转换的字符串 */ printf("inbuf=%s\n", inbuf); /* 打印需要转换的字符串的长度 */ printf("inlen=%d\n", *inlen); /* 由于iconv()函数会修改指针,所以要保存源指针 */ char *tmpin = inbuf; char *tmpout = outbuf; size_t insize = *inlen; size_t outsize = *outlen; /* 进行转换 *@param cd iconv_open()产生的句柄 *@param srcstart 需要转换的字符串 *@param inlen 存放还有多少字符没有转换 *@param tempoutbuf 存放转换后的字符串 *@param outlen 存放转换后,tempoutbuf剩余的空间 * * */ size_t ret = iconv (cd, &tmpin, inlen, &tmpout, outlen); if (ret == -1) { perror ("iconv"); } /* 存放转换后的字符串 */ printf("outbuf=%s\n", outbuf); //存放转换后outbuf剩余的空间 printf("outlen=%d\n", *outlen); int i = 0; for (i=0; i<(outsize- (*outlen)); i++) { //printf("%2c", outbuf[i]); printf("%x\n", outbuf[i]); } /* 关闭句柄 */ iconv_close (cd); return 0; } bool utf8_to_unicode (char *inbuf, size_t *inlen, char *outbuf, size_t *outlen) { /* 目的编码, TRANSLIT:遇到无法转换的字符就找相近字符替换 * IGNORE :遇到无法转换字符跳过*/ char *encTo = "UNICODE//IGNORE"; /* 源编码 */ char *encFrom = "UTF-8"; /* 获得转换句柄 *@param encTo 目标编码方式 *@param encFrom 源编码方式 * * */ iconv_t cd = iconv_open (encTo, encFrom); if (cd == (iconv_t)-1) { perror ("iconv_open"); } /* 需要转换的字符串 */ printf("inbuf=%s\n", inbuf); /* 打印需要转换的字符串的长度 */ printf("inlen=%d\n", *inlen); /* 由于iconv()函数会修改指针,所以要保存源指针 */ char *tmpin = inbuf; char *tmpout = outbuf; size_t insize = *inlen; size_t outsize = *outlen; /* 进行转换 *@param cd iconv_open()产生的句柄 *@param srcstart 需要转换的字符串 *@param inlen 存放还有多少字符没有转换 *@param tempoutbuf 存放转换后的字符串 *@param outlen 存放转换后,tempoutbuf剩余的空间 * * */ size_t ret = iconv (cd, &tmpin, inlen, &tmpout, outlen); if (ret == -1) { perror ("iconv"); } /* 存放转换后的字符串 */ printf("outbuf=%s\n", outbuf); //存放转换后outbuf剩余的空间 printf("outlen=%d\n", *outlen); int i = 0; for (i=0; i<(outsize- (*outlen)); i++) { //printf("%2c", outbuf[i]); printf("%x\n", outbuf[i]); } /* 关闭句柄 */ iconv_close (cd); return 0; } int main () { /* 需要转换的字符串 */ //char inbuf[1024] = "abcdef哈哈哈哈行"; char *text = "汉"; char inbuf[1024] = {}; strcpy (inbuf, text); size_t inlen = strlen (inbuf); /* 存放转换后的字符串 */ char outbuf[1024] = {}; size_t outlen = 1024; utf8_to_unicode (inbuf, &inlen, outbuf, &outlen); printf ("print outbuf: %s\n", outbuf); size_t outsize = strlen(outbuf); size_t insize = 1024; char instr[1024] = {}; unicode_to_utf8 (outbuf, &outsize, instr, &insize); printf ("print buf: %s\n", instr); return 0; }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 张高兴的大模型开发实战:(一)使用 Selenium 进行网页爬虫
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构