需要使用到的三个函数:
#include <iconv.h>
iconv_t iconv_open(const char *tocode, const char *fromcode);
size_t iconv(iconv_t cd, char **inbuf, size_t *inbytesleft, char **outbuf, size_t *outbytesleft);
int iconv_close(iconv_t cd);
iconv_open() 为从 fromcode 到 tocode 进行编码转换分配一个适合的转换描述字,并作为返回值返回。
fromcode 和 tocode 的值依赖于系统,在 GNU C 库下,可以使用 iconv --list 命令查看所有被支持的编码。
转换描述字在调用 iconv_close() 释放前能够被 iconv() 无限次调用。
转换描述字包含一个转换状态,调用 iconv_open() 分配后,该状态为初始状态,而调用 iconv() 后,该状态被改变(这意味着转换描述字不能被多线程同时使用),要恢复为初始状态,可以调用 iconv() 时将 inbuf 参数指定为 NULL 。
iconv_open() 调用成功则返回一个新的转换描述字,失败则返回 (iconv_t)-1 并设置 errno 值。发生的错误有:
EINVAL 从 fromcode 到 tocode 的编码转换不被支持。
iconv() 执行一次编码转换。
参数 cd 必须是调用 iconv_open() 返回的转换描述字。
当 inbuf 和 *inbuf 都不为 NULL 时, iconv() 将从 *inbuf 中读取最多 *inbytesleft 字节的数据转换后写入 *outbuf 中,写入的数据最多 *outbytesleft 字节。
iconv() 进行转换时每次转换一个多字节字符,在循环转换每个字符时,它都增大 *inbuf 并减小 *inbytesleft 读取的字节数,同时也增大 *outbuf 并减小 *outbytesleft 被写入的字节数,并改变包含在转换描述字 cd 中的转换状态。转换在四种情况下将被中止:
1、要进行转换的多字节字符串是非法的,无法完成转换。这种情况下,将把 errno 设置为 EILSEQ 并返回 (size_t)-1 , *inbuf 将指向非法字符串的开始。
2、字符串未被全部转换,例如, *inbytesleft 在完全转换前减为 0 。在这种情况下, iconv() 将返回已被转换的字节数。
3、要进行转换的多字节字符串不完整,比如 UCS-2 编码中一个汉字应该是2个字节,但字符串的最后只有一个字节该字符串就结束了,这种情况下,将设置 errno 为 EINVAL 并返回 (size_t)-1 ,*inbuf 将指向这个不完整字符串的开始。
4、没有足够的空间存放转换后的数据,这种情况下,将设置 errno 为 E2BIG 并返回 (size_t)-1 。
如果 inbuf 或 *inbuf 为 NULL ,并且 outbuf 和 *outbuf 不为 NULL 时, iconv() 将试着设置转换描述字 cd 的转换状态为初始状态,并在 *outbuf 中记录最多 *outbytesleft 字节的转换序列。但如果没有足够的空间存放改重设序列,将会设置 errno 为 E2BIG 并返回 (size_t)-1 ,否则会增大 *outbuf 和减小 *outbytesleft 被写入的字节数。
如果 inbuf 或 *inbuf 为 NULL ,并且 outbuf 或 *outbuf 也为 NULL 时, iconv() 将只是设置转换描述字 cd 的转换状态为初始状态。
iconv() 调用成功时返回以不可逆方式转换的字符的数目,可逆的转换将不会计算,失败时返回 (size_t)-1 并设置 errno 值。发生的错误有:
E2BIG 在 *outbuf 中没有足够的空间。
EILSEG 要进行转换的字符串为非法字符串。
EINVAL 要进行转换的字符串不完整。
要想得到转换后的数据的字节数,需要用转换开始前的 *outbytesleft 减去转换完成后的 *outbytesleft 。
iconv_close() 释放此前由 iconv_open() 分配的转换描述字。
iconv_close() 调用成功时返回 0 ,失败时返回 -1 并设置 errno 值。
下面这个函数将实现编码的转换:
++++++++++++++++++++++++++++++++++++++++++++++++++
#include <iconv.h>
/************************************************************************************/
/* 功能描述:将 in 中的数据由 fromcode 编码转换为 tocode 编码,并将结果由 out 输出 */
/* 参数说明: */
/* [out]out 转换后存放结果的缓冲区 */
/* [in]outlen out缓冲区的大小 */
/* [in]in 要进行转换的初始数据 */
/* [in]inlen in缓冲区的大小 */
/* [in]tocode 目的编码 */
/* [in]fromcode 源编码 */
/* 返回值: 成功则返回转换后结果的字节数大小;失败则返回 -1 并置 errno 为相应的值 */
/************************************************************************************/
size_t code_conv(char *out, size_t outlen, char *in, size_t inlen, const char *tocode, const char *fromcode)
{
iconv_t cd;
size_t olen = outlen;
cd = iconv_open(tocode, fromcode);
if (cd == (iconv_t)-1) return -1;
if (iconv(cd, &in, &inlen, &out, &outlen) == (size_t)-1)
return -1;
iconv_close(cd);
return olen - outlen;
}
++++++++++++++++++++++++++++++++++++++++++++++++++