c++利用iconv实现编码转换类

iconv的原型如下:
	size_t iconv(iconv_t cd,
                 char **inbuf,
                 size_t *inbytesleft,
                 char **outbuf,
                 size_t *outbytesleft);

此函数利用函数参数,同时返回了好几个值,每个函数参数既是入参,也是出参。

作为入参

  1. cd是转换句柄。
  2. inbuf是输入字符串的地址的地址。
  3. inbytesleft是输入字符串的长度。
  4. outbuf是输出缓冲区的首地址
  5. outbytesLeft 是输出缓冲区的长度。

作为出参

  1. cd是转换句柄。
  2. inbuf指向剩余字符串的地址
  3. inbytesleft是剩余字符串的长度。
  4. outbuf是输出缓冲区剩余空间的首地址
  5. 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

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值