多种国际编码格式之间进行文本内码的转换

作为编程接口的iconv包括3个函数:

iconv_open函数:用于初始化用于转换的内部缓冲区,指明需要从何种编码方式转换到哪一种。

iconv函数:进行实际的转换,需要给出两个间接缓冲区指针和剩余字节数指针。该函数需要更新所有相关信息,因此将不可改写的指针传递给iconv是错误的。

iconv_close函数:释放iconv_open函数的缓冲区。

注:由于没有办法获取转换之后需要的内存大小,所以可能会造成内存空间的浪费!


iconv_open函数

#include <iconv.h>
iconv_t iconv_open(const char* tocode,const char* fromcode);


描述:

iconv_open()函数申请一个转换描述符,转换字符序列从编码fromcode到编码tocode转换描述符包含转换状态,调用iconv_open创建以后,转换状态处于初始状态,调用iconv函数以后改变转换描述符的转换状态,(意味着转换描述符不能在多线程中同时使用


返回值:

iconv_open函数返回一个新申请的转换描述符,出错时,返回(iconv_t)-1;



iconv函数

#include <iconv.h>  
size_t iconv(iconv_t cd, char **restrict inbuf, size_t *restrict inbytesleft, char **restrict outbuf, size_t *restrict outbytesleft);   


参数说明:

inconv_t cd:函数iconv_open()分配的编码转换句柄。

char **restrict inbuf:指向需要编码转换的缓冲区。(其中关键字restrict只用于限定指针;该关键字用于告知编译器,所有修改该指针所指向内容的操作全部都是基于(base on)该指针的,即不存在其它进行修改操作的途径;这样的后果是帮助编译器进行更好的代码优化,生成更有效率的汇编代码。)

size_t *restrict inbytesleft:inbuf中还需要编码转换的字节数。

char **restrict outbuf:指向存放转码的缓冲区。

size_t *restrict outbytesleft:outbuf中还可以存放转码的字节数,也就是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设置转换状态为初始状态



iconv_close函数

int iconv_close(iconv_t cd); 

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



示例代码:

封装一个转换类型:

class CCodeConverter
{
 public:
    CCodeConverter(const char * fromCode, const char * toCode)
    {
        hCodeConverter=iconv_open(toCode, fromCode);
    }

    ~CCodeConverter()
    {
        iconv_close(hCodeConverter);
    }

    //进行转换
    int convert(char * srcBuf, int srcLen, char * destBuf, int destLen)
    {
        //返回转换的字符个数
        int nConv=iconv(hCodeConverter, &srcBuf, (size_t *)&srcLen, &destBuf, (size_t *)&destLen);
        //如果错误,则获取错误码
        nErr=errno;
        return nConv;
    }

    //获取错误信息
    int getErrInfo()
    {
        switch(nErr)
        {
            case E2BIG:
                {
                    printf("errno:E2BGI(OutBuf空间不够)\n");
                    break;
                }
            case EILSEQ:
                {
                    printf("errno:EILSEQ(InBuf多字节序无效)\n");
                    break;
                }
            case EINVAL:
                {
                    printf("errno:EINVAL(有残留的字节未转换)\n");
                    break;
                }
            default:
                break;
        }
        return nErr;
    }

 private:
    //转换句柄
    iconv_t hCodeConverter;
    int nErr;
};

以utf-8转为utf-16为例
</pre><p><pre name="code" class="cpp">int main()
{
    int srcLen=12;
    char * srcBuf=new char[srcLen];
    memset(srcBuf, 0, srcLen);

    strcpy(srcBuf, "BaiSe");

    int destLen=2*srcLen;
    char * destBuf=new char[destLen];
    memset(destBuf, 0, destLen);

    CCodeConverter cv=CCodeConverter("utf-8", "utf-16");
    int nRet=cv.convert(srcBuf, srcLen, destBuf, destLen);

    if(nRet<0)
    {
        cv.getErrInfo();
        return -1;
    }
    printf("转换成功\n");
    
    return 0; 
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值