Linux下编码转换(iconv函数族)

5 篇文章 0 订阅

转自:http://www.linuxdiyf.com/viewarticle.php?id=45164

在Linux上进行编码转换时,既可以利用iconv函数族编程实现,也可以利用iconv命令来实现(针对文件进行转换) 

一、利用iconv函数族进行编码转换 

iconv函数族的头文件是iconv.h

使用前需包含之:#include <iconv.h>

iconv函数族有三个函数,原型如下:

(1) iconv_open()

函数原型:

iconv_t iconv_open(const char *tocode, const char *fromcode); 

函数功能:

该函数分配一个编码转换句柄

参数:

1> tocode是目标编码

2> fromcode是原编码

(具体可以使用的编码方案可以百度查找)

支持的内码包括:Unicode相关编码,如UTF-8、UTF-16等等;各国采用的ANSI编码,其中包括GB2312、BIG5等中文编码方式。

返回值:

调用成功,则该函数返回一个转换句柄,供以下两个函数使用;

调用失败,返回-1,并且设置errno

可能的错误类型:

EINVAL The  conversion  from fromcode to tocode is not supported by the implementation.

(2) iconv()

函数功能:进行实际的编码转换

函数原型:

size_t iconv(iconv_t cd,
                    char **inbuf, size_t *inbytesleft,
                    char **outbuf, size_t *outbytesleft);

参数介绍:

1> cd是方法iconv_open()调用返回的转码句柄;

2> inbuf指向需要转码的缓冲区;

3> inbytesleft是inbuf所保存的需要转码的字节数;

4> outbuf存放转码结果;

5> outbytesleft存放outbuf空间的大小。

(不足之处:由于没有办法获取转换之后需要的内存大小,所以会造成内存空间的浪费!)

返回值:

调用成功,返回转换的字节数(不可逆转调用的字节数,可逆转调用的字节数不包括在内

调用失败,返回-1,并设置相应的errno。

注意:

 iconv()是逐步扫描inbuf,每转换一个字符,就增加inbuf,减少inbytesleft,并将结果存入outbuf,结果字节数存入outbytesleft

常见的三种情况:

情况一: inbuf不为空,而且*inbuf也不为空

此时,进行正常的编码转换

遇到下列情况将停止扫描并返回:

(1)inbuf中碰到非法的多字节序

这种状况下,会设置errno为EILSEQ,并返回-1;

(2)inbuf字节被完全转换

这种状况下,返回转换的字节数

(3)inbuf中碰到不完整的多字节序

这种状况下,设置errno为EINVAL,并返回-1;

(4)outbuf中没有足够的空间以进行下一次的字符转换

这种状况下,设置errno为E2BIG,并返回-1;

情况二:inbuf == NULL,或者*inbuf == NULL;但outbuf != NULL,且*outbuf != NULL

iconv会设置转换状态为初始状态,并保存转换序列到*outbuf。如果outbuf空间不足,errno会设置为E2BIG,返回(size_t) (-1);

情况三:INBUF == NULL,或者*inbuf == NULL; 并且outbuf == NULL,*out == NULL

iconv设置转换状态为初始状态

(3) iconv_close()

函数原型:

int iconv_close(iconv_t cd); 

函数功能:

此函数用于关闭转换句柄,释放资源。

示例代码:

封装一个转换类型:

[cpp]  view plain copy
  1. class CCodeConverter  
  2. {  
  3.  public:  
  4.     CCodeConverter(const char * fromCode, const char * toCode)  
  5.     {  
  6.         hCodeConverter=iconv_open(toCode, fromCode);  
  7.     }  
  8.   
  9.   
  10.     ~CCodeConverter()  
  11.     {  
  12.         iconv_close(hCodeConverter);  
  13.     }  
  14.   
  15.   
  16.     //进行转换  
  17.     int convert(char * srcBuf, int srcLen, char * destBuf, int destLen)  
  18.     {  
  19.         //返回转换的字符个数  
  20.         int nConv=iconv(hCodeConverter, &srcBuf, (size_t *)&srcLen, &destBuf, (size_t *)&destLen);  
  21.   
  22.   
  23.         //如果错误,则获取错误码  
  24.         nErr=errno;  
  25.   
  26.   
  27.         return nConv;  
  28.     }  
  29.   
  30.   
  31.     //获取错误信息  
  32.     int getErrInfo()  
  33.     {  
  34.         switch(nErr)  
  35.             {  
  36.             case E2BIG:  
  37.                 {  
  38.                     printf("errno:E2BGI(OutBuf空间不够)\n");  
  39.                     break;  
  40.                 }  
  41.             case EILSEQ:  
  42.                 {  
  43.                     printf("errno:EILSEQ(InBuf多字节序无效)\n");  
  44.                     break;  
  45.                 }  
  46.             case EINVAL:  
  47.                 {  
  48.                     printf("errno:EINVAL(有残留的字节未转换)\n");  
  49.                     break;  
  50.                 }  
  51.             default:  
  52.                 break;  
  53.             }  
  54.   
  55.   
  56.         return nErr;  
  57.     }  
  58.   
  59.   
  60.  private:  
  61.     //转换句柄  
  62.     iconv_t hCodeConverter;  
  63.     int nErr;  
  64. };  

以utf-8转为utf-16为例

[cpp]  view plain copy
  1. int main()  
  2. {  
  3.     int srcLen=12;  
  4.     char * srcBuf=new char[srcLen];  
  5.     memset(srcBuf, 0, srcLen);  
  6.   
  7.   
  8.     strcpy(srcBuf, "BaiSe");  
  9.   
  10.   
  11.     int destLen=2*srcLen;  
  12.     char * destBuf=new char[destLen];  
  13.     memset(destBuf, 0, destLen);  
  14.   
  15.   
  16.     CCodeConverter cv=CCodeConverter("utf-8""utf-16");  
  17.     int nRet=cv.convert(srcBuf, srcLen, destBuf, destLen);  
  18.   
  19.   
  20.     if(nRet<0)  
  21.     {  
  22.         cv.getErrInfo();  
  23.         return -1;  
  24.     }  
  25.   
  26.   
  27.     printf("转换成功\n");     
  28. }  
调试,查看内存,destBuf内容如下:

(gdb) print destBuf
$1 = 0x804b018 "\377\376B"
(gdb) print destBuf+1
$2 = 0x804b019 "\376B"
(gdb) print destBuf+2
$3 = 0x804b01a "B"
(gdb) print destBuf+3
$4 = 0x804b01b ""
(gdb) print destBuf+4
$5 = 0x804b01c "a"
(gdb) print destBuf+5
$6 = 0x804b01d ""
(gdb) print destBuf+6

$7 = 0x804b01e "i"

问题:不明白为什么前面有"\377\376",是用来标识编码类型的么?

二、iconv命令

iconv命令用于转换指定文件的编码,默认输出到标准输出设备,亦可指定输出文件。

用法: iconv [选项...] [文件...]

有如下选项可用:

输入/输出格式规范:

-f, --from-code=名称 原始文本编码
-t, --to-code=名称 输出编码信息:
-l, --list 列举所有已知的字符集输出控制:
-c 从输出中忽略无效的字符
-o, --output=FILE 输出文件
-s, --silent 关闭警告
--verbose 打印进度信息
-?, --help 给出该系统求助列表
--usage 给出简要的用法信息

-V, --version 打印程序版本号

例子:

iconv -f utf-8 -t gb2312 aaa.txt >bbb.txt

这个命令读取aaa.txt文件,从utf-8编码转换为gb2312编码,其输出定向到bbb.txt文件。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值