作为编程接口的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;
}