字符集、字符编码与 iconv 笔记

字符集和字符编码

很多相关文章都模糊了字符集和字符编码的概念。字符集和字符编码(Charset & Encoding)这篇文章非常赞,简明扼要,介绍了两者的概念以及常用字符集和字符编码。

另外,关于所谓 ANSI 编码。ANSI(American National Standards Institute,ANSI)是负责制定美国国家标准的非营利组织。它针对不同的地区与国家,定义了一系列的支持不同语言字符集的代码页。所以各国字符集和字符编码被 统称 为 ANSI。

ANSI 不同的语言使用不同的字符集和字符编码,所以跨语言不能通用,会出现乱码。ANSI 没有很明显的特征 Xcode 或一些文本编辑器打开可能乱码。

最通用的编码是 UTF-8 without BOM。Windows 里的软件一般都默认有 BOM,而其它系统都默认没有 BOM。Visual Studio 下可以在 文件 -> 高级保存选项 更改编码。

iconv 的一个类型,三个函数

  • 数据类型:iconv_t
    这是 iconv 中定义的一个抽象类型,不要去对它做任何假设,因为它必须完全地是不明确的。
    当使用 iconv 函数时,该类型的对象会被赋值为 转换 的句柄。对象本身不需要释放,但是句柄所表示的 转换 需要释放。

  • 函数:iconv_t iconv_open (const char* tocode, const char* fromcode);
    转换开始前必须使用该函数初始化。两个参数分别是转换的目标字符集和需要转换的源字符集。如果转换可以执行,返回一个句柄;否则返回 -1。

  • 函数:size_t iconv (iconv_t cd, char* * inbuf, size_t *inbytesleft, char* * outbuf, size_t *outbytesleft);
    该函数根据 cd 将 输入缓冲中的文本进行转换,并将结果保存于输出缓冲中。*outbuf 指向一个至少有 *outbytesleft 个字节空间来保存结果的缓冲区的开始处。

  • 函数:int iconv_close (iconv_t cd);
    释放与句柄 cd 相关的全部资源,当然前提是正确调用了 iconv_open 函数。

进一步阅读:Generic Character Set Conversion Interface

gbk -> utf-8 转换示例

bool Chinese::iconvConvert(const char* from_charset, const char* to_charset, char* inbuf, int inlen, char* outbuf, int outlen)
{
    iconv_t cd=iconv_open(to_charset, from_charset);
    if(cd==0)
        return false;
    char** pin=&inbuf;
    char** pout=&outbuf;
    memset(outbuf, 0, outlen);
    size_t ret=iconv(cd, pin, (size_t*)&inlen, pout, (size_t*)&outlen);
    iconv_close(cd);
    return ret==(size_t)(-1)? false: true;
}

string Chinese::iconvGbkToUtf8(const string& str)
{
    string inStr = str;
    char* textIn = (char*)inStr.c_str();
    int inLen = str.length();
    int outLen = inLen * 2 + 1;
    char* textOut = (char*)malloc(outLen);
    bool ret = false;
    if (textOut)
        ret = iconvConvert("gbk", "utf-8", textIn, inLen, textOut, outLen);
    string strOut = ret ? string(textOut) : string();
    free(textOut);

    return strOut;
}