libiconv 的安装 和 使用

来源:互联网 发布:微信公众平台数据统计 编辑:程序博客网 时间:2024/06/07 09:29

libiconv是实现字符集转换的类库


libiconv的安装:

1.首先从官网下载wget http://ftp.gnu.org/gnu/libiconv/libiconv-1.14.tar.gz

然后解压到/usr/local/src

tar -zxvf libiconv-1.14.tar.gz -C /usr/local/src


2. 编译安装

./configure --prefix=/usr/local

make


make的时候会出现错误 

出现gets   srclib相关的一些报错信息

解决办法是进入srclib目录 执行如下命令

sed -i -e '/gets is a security/d' ./stdio.in.h


然后重新执行

./configure --prefix=/usr/local

make

make install


3.根据要求还要重新编译和安装gettext

我就直接从官网重新下载了最新的gettext0.19

同样的解压  编译

./configure --prefix=/usr/local

make

make install


此后再进入libiconv文件夹

首先make distclean

然后顺序

./configure --prefix=/usr/local

make

make install

即可


libiconv的使用

1.首先进入/usr/local/bin

输入iconv --help

会出现错误:找不到libiconv.so.2


解决办法是:

vim /etc/ld.so.conf

加入一行/usr/local/lib

保存退出

然后/sbin/ldconfig即可


2.libiconv的使用主要使用以下几个函数

首先 #include <iconv.h>

iconv库主要使用以下几个iconv_open  iconv_close iconv

根据文档几个函数的声明分别如下:

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

iconv_open函数申请一个转换描述符,转换字节序列从编码fromcode到编码tocode

fromcodetocode允许的值依赖于本地系统。


iconv的结果转换描述符能使用任意多次,直到调用iconv_close函数释放掉。

 

转换描述符包含转换状态。调用iconv_open创建后,转换状态处于初始状态。调用iconv将改变描述符的转换状态。(意味着转换描述符不能在多线程中同时使用。)把转换状态恢复至初始状态,只需把NULL作为inbuf参数来调用iconv


iconv_open函数返回一个新申请的转换描述符。出错时,将修改errno并返回(iconv_t)(-1)

除了其它错误以外,还会出现以下错误:

EINVAL

    fromcodetocode编码转换不被支持。


(2)

size_t iconv (iconv_t cd,

              const char* * inbuf, size_t * inbytesleft,

              char* * outbuf, size_t * outbytesleft);

 

描述

参数cd必须是由iconv_open函数创建的转换描述符。

 

大部分情形是inbuf 不为NULL*inbuf不为NULL。这种情况下,iconv函数将以*inbuf起始的多字节序列转换到以*outbuf起始的多字节序列。从*inbuf开始读取,最多*inbytesleft字节,转换后,从*outbuf开始写入,最多*outbytesleft字节。

 

iconv函数一次转换一个多字节字符,每次字符转换,*inbuf增加已转换的字节数,*inbytesleft相应地减少已转换的字节数;对应地,*outbuf*outbytesleft作相应的修改,同时修改cd的转换状态。

也就是说iconv会修改inbuf和outbuf指针 

编程需要进行预存

 

以下四种情况不能完成转换:

1.输入中含无效的多字节序列。此时,它errno设置为EILSEQ并返回(size_t)(-1)*inbuf指向无效序列的最左端。

2.输入的字节序列已经全部被转换过,也就是*inbytesleft减少至0。此时,iconv返回本次调用中完成转换的数目(可逆的转换不计入)

3.输入中以不完整多字节序列作结尾。此时,它errno设置为EINVAL并返回(size_t)(-1)*inbuf指向不完整多字节序列的最左端。

4.输出缓存区没有足够空间来存储下一个字符。此时,它errno设置为E2BIG并返回(size_t)(-1)

 

另一种情形inbuf NULL*inbufNULL,但*outbuf 不为NULL*outbuf不为NULL。这种情况下,iconv函数试图将cd的转换状态设置为初始状态并store a corresponding shift sequence at *outbuf。从*outbuf开始,最多写入*outbytesleft字节。如果输出缓存区没有足够空间来存储这个重置后的序列,他将errno设置为E2BIG并返回(size_t)(-1)。反之,*outbuf增加写入的字节数*outbytesleft减少写入的字节数。

 

第三种情形inbuf NULL*inbufNULL*outbuf NULL*outbufNULL。这种情况下,iconv函数试图将cd的转换状态设置为初始状态。

 

返回值

iconv函数返回本次调用中转换的字符数,可逆的转换不计入。出错时,它将修改errno并返回(size_t)(-1)

 

错误

除了其它错误以外,出现以下错误:

E2BIG

*outbuf没有足够的空间。

EILSEQ

    输入含无效的多字节序列。

EINVAL

    输入含不完整多字节序列。


(3)

int iconv_close (iconv_t cd);

描述

iconv_close函数释放由iconv_open 函数申请的转换描述符cd

返回值

成功,iconvctl函数返回0。出错时,它修改errno并返回(size_t)(-1)


3.liciconv编程相关

我在linux 下进行的编程  实现UTF-8到GB2312的转换

主要需要注意一下几个方面:

(1)大概函数如下:

//转换成功返回转换成功的字符长度,不成功返回1
int utf8ToGb2312(char *dest,size_t destLen,char *src)
{
     //int argument=1;
     char *oldsrc=src;  //记录源地址值
     char *olddest=dest;  //记录目标地址值
     //printf("%s\n",oldsrc);
     memset(dest,0,destLen);  //将目标字符串置0
     size_t srcLen=strlen(src);     //源字符串长度
    printf("srcLen=%u\n",srcLen);
    iconv_t converter=iconv_open("GB2312","UTF-8");
    //iconv_open第一个参数为tocode,第二个参数为fromcode
    if(converter==(iconv_t)(-1))    //若转换失败
    {
        printf("encode convert not supported\n");
        if(errno==EINVAL)
            printf("einval\n");
        return -1;
    }
    else{
        printf("OK!\n");
    }


     size_t rc=iconv(converter,&src,&srcLen,&dest,&destLen);
     printf("rc=%u\n",rc);


     dest=olddest;
     src=oldsrc;
     //由于iconv函数会修改输出字符串和输入字符串的地址
     // 因此需要通过原始值获得转换后的字符串
     iconv_close(converter);
     //关闭转换器
     return (int)rc;
}



主要注意iconv函数会修改输出字符串和输入字符串的地址

因此需要通过保存原始值获得转换后的字符串


(2)出现libiconv_open undefined reference的问题 

参见转载的文章:《libiconv库链接问题》


4.血泪的教训

我想实现UTF-8到UTF-16的转换 

中文转换 都很正常 可是英文问题就很多 总是到英文就截止了

无法得到想要的结果

经过两三个小时的查错 我才发现原因在于英文字母  例如a 在UTF-8中是一个非0字符

而在UTF-16中会变成两个字符 而且首字符为0

就会导致strlen或是printf等函数都无法实现输出


而且iconv也不能正确返回准确的字符数

因此这种情况下 建议自己根据UTF-8 到UTF-16的转换自己实现

我已经实现了相关函数 具体实现见文章《UTF-8 到UTF -16 转换C程序》

0 0
原创粉丝点击