iconv的原型如下:
size_t iconv(iconv_t cd,
char **inbuf,
size_t *inbytesleft,
char **outbuf,
size_t *outbytesleft);
此函数利用函数参数,同时返回了好几个值,每个函数参数既是入参,也是出参。
作为入参
- cd是转换句柄。
- inbuf是输入字符串的地址的地址。
- inbytesleft是输入字符串的长度。
- outbuf是输出缓冲区的首地址
- outbytesLeft 是输出缓冲区的长度。
作为出参
- cd是转换句柄。
- inbuf指向剩余字符串的地址
- inbytesleft是剩余字符串的长度。
- outbuf是输出缓冲区剩余空间的首地址
- outbytesLeft 是输出缓冲区剩余空间的长度。
#ifndef _CODECONVERTER__H_
#define _CODECONVERTER__H_
#include <iconv.h>
#include <cstring>
#include <iostream>
#define OUTLEN 255
using namespace std;
class CodeConverter
{
public:
CodeConverter(const char *from_charset,const char *to_charset);
~CodeConverter(void);
int convert(char *inbuf, int inlen, char *outbuf, int outlen);
int getErrInfo();
private:
iconv_t cd;
int nErr;
};
#endif
#include "CodeConverter.h"
#include <stdio.h>
#include <errno.h>
CodeConverter::CodeConverter(const char *from_charset,const char *to_charset)
: cd(NULL)
, nErr(0)
{
if(!cd)
{
cd = iconv_open(to_charset,from_charset);
if(cd == (iconv_t)-1)
{
nErr = errno;
perror("iconv_open");
}
}
}
CodeConverter::~CodeConverter(void)
{
if(cd)
{
iconv_close(cd);
cd =NULL;
}
}
int CodeConverter::convert(char *inbuf, int inlen, char *outbuf, int outlen)
{
int nRet =0;
do{
if (!cd)
{
nRet =-2;
break;
}
// int one = 1;
// iconvctl(cd,ICONV_SET_DISCARD_ILSEQ,&one);
char **pin = &inbuf;
char **pout = &outbuf;
size_t inlenTemp = (size_t)inlen;
size_t outlenTemp = (size_t)outlen;
cout<<"inlenTemp:"<<inlenTemp<<",outlenTemp:"<<outlenTemp<<endl;
memset(outbuf, 0, outlenTemp);
nRet = iconv(cd, pin, &inlenTemp, pout, &outlenTemp);
if(nRet < 0)
{
nErr = errno;
cout<<"iconv-nRet:"<<nRet<<", errno:"<<nErr<<",handle:"<<cd<<endl;
cout<<"EILSEQ:"<<EILSEQ<<", E2BIG:"<<E2BIG<<", EINVAL:"<<EINVAL<<endl;
getErrInfo();
nRet = nErr;
}
else
{
inlen -= inlenTemp;
outlen -= outlenTemp;
}
} while (0);
return nRet;
}
int CodeConverter::getErrInfo()
{
switch(nErr)
{
case E2BIG:
{
cout<<"errno:E2BGI(OutBuf空间不够)"<<endl;
break;
}
case EILSEQ:
{
cout<<"errno:EILSEQ(InBuf多字节序无效)"<<endl;
break;
}
case EINVAL:
{
cout<<"errno:EINVAL(有残留的字节未转换)"<<endl;
break;
}
default:
cout<<"errno:ELSE(无效的或不完整的多字节或宽字符)"<<endl;
break;
}
return nErr;
}
int main()
{
/*
char inbuf[64] = {0};
strcpy(inbuf,"huqin");
int inlen = strlen(inbuf);
char outbuf[64] = {0};
int outlen = 128;
CodeConverter cvter( "utf-8" , "GBK" );
int nRet;
nRet = cvter.convert(inbuf,inlen,outbuf,outlen);
cout<<"outbuf:"<<outbuf<<endl;
*/
CodeConverter cc("utf-8", "GBK");
std::string channelName = "huqin";
char tempName[128] = {0};
int nRet;
size_t iLenIn = channelName.length();
size_t iLenOut = sizeof(tempName) - 1;
nRet = cc.convert((char *)channelName.c_str(), iLenIn, tempName, iLenOut);
cout << "resolved the code size:" << nRet << endl ;
if(!nRet)
{
cout<<"outbuf:"<<tempName<<endl;
//strncpy(chName.chNameStr[0].name, tempName, sizeof(chName.chNameStr[0].name) - 1);
}
return 0;
}
编译运行:
huqin@ubuntu:/mnt/hgfs/share/code/2021/mon10/week1$ g++ CodeConverter.h CodeConverter.cpp -o convert
huqin@ubuntu:/mnt/hgfs/share/code/2021/mon10/week1$ ./convert
inlenTemp:5,outlenTemp:127
outbuf:huqin