网上典型的代码是这一段:

char* ConvertEnc( char *encFrom, char *encTo, const char * in)
{static char bufin[1024], bufout[1024], *sin, *sout;int lenin, lenout, ret;iconv_t c_pt;if ((c_pt = iconv_open(encTo, encFrom)) == (iconv_t)-1){printf("iconv_open false: %s ==> %s", encFrom, encTo);return NULL;}iconv(c_pt, NULL, NULL, NULL, NULL);lenin  = strlen(in) + 1;lenout = 1024;sin    = (char *)in;sout   = bufout;ret = iconv(c_pt, (const char**)&sin, (size_t *)&lenin, &sout, (size_t *)&lenout);if (ret == -1){return NULL;}iconv_close(c_pt);return bufout;
}

这段代码里面有3个问题:
1.没有重复使用初始化后的iconv_t。
2.lenin  = strlen(in) + 1这行代码在某些情况下有问题。
3.转换缓冲区是一个固定值。

我根据iconv官网上的文档重写了相关代码,官网地址如下:

http://www.gnu.org/savannah-checkouts/gnu/libiconv

代码如下

#ifndef _ICONV_PAIR_HXX_
#define _ICONV_PAIR_HXX_#include <string>
#include <iconv/include/iconv.h>class IconvPair
{enum {INIT_BUFFER = 4096};public:IconvPair(const std::string &toCode, const std::string &fromCode);~IconvPair();private:IconvPair(const IconvPair&);IconvPair& operator=(const IconvPair&);public:friend bool operator<(const IconvPair &lhs, const IconvPair &rhs){if (lhs.mToCode < rhs.mToCode){return true;}else if (lhs.mToCode > rhs.mToCode){return false;}return lhs.mFromCode <=rhs.mFromCode ? true : false;}const char* buffer() const {return mBuffer;}size_t bufferLen() const {return mBufferLen;}size_t contentLen() const {return mContentLen;}size_t convert(const char **inBuffer, size_t *inBytesLeft);private:void incBuffer();private:std::string mToCode;std::string mFromCode;iconv_t mIconv;char *mBuffer;size_t mBufferLen;size_t mContentLen;
};#endif
#include "statistics/IconvPair.hxx"
#include <cstdlib>
#include <cerrno>
#include <cassert>
#include <climits>
#include <exception>IconvPair::IconvPair(const std::string &toCode, const std::string &fromCode): mToCode(toCode), mFromCode(fromCode), mIconv(reinterpret_cast<iconv_t>(-1)), mBuffer(NULL), mBufferLen(0), mContentLen(0)
{if (mToCode.empty() || mFromCode.empty()){throw std::exception();}mBufferLen = INIT_BUFFER;mBuffer = reinterpret_cast<char*>(malloc(mBufferLen));if (NULL == mBuffer){throw std::bad_alloc();}mIconv = iconv_open(toCode.c_str(), fromCode.c_str());if (reinterpret_cast<iconv_t>(-1) == mIconv){throw std::exception();}
}IconvPair::~IconvPair()
{if (reinterpret_cast<iconv_t>(-1) != mIconv){iconv_close(mIconv);}free(mBuffer);
}size_t IconvPair::convert(const char **inBuffer, size_t *inBytesLeft)
{assert((NULL != mBuffer) && (reinterpret_cast<iconv_t>(-1) != mIconv));assert((NULL != inBuffer) && (NULL != *inBuffer) && (NULL != inBytesLeft));iconv(mIconv, NULL, NULL, NULL, NULL);char *outBuffer = mBuffer;size_t outBytesLeft = mBufferLen;size_t ret = iconv(mIconv, inBuffer, inBytesLeft, &outBuffer,&outBytesLeft);while ((UINT_MAX == ret) && (0 == outBytesLeft)/*(E2BIG == errno)*/){size_t oldBufferLen = mBufferLen;incBuffer();outBuffer = mBuffer + oldBufferLen;outBytesLeft = mBufferLen - oldBufferLen;ret = iconv(mIconv, inBuffer, inBytesLeft, &outBuffer,&outBytesLeft);}mContentLen = mBufferLen - outBytesLeft;if (0 == outBytesLeft){incBuffer();}mBuffer[mContentLen] = 0;return ret;
}void IconvPair::incBuffer()
{mBufferLen *= 2;mBuffer = reinterpret_cast<char*>(realloc(mBuffer, mBufferLen));if (NULL == mBuffer){throw std::bad_alloc();}
}

测试代码块如下:

void UnitTest::testIconv()
{const size_t pageSize = 4096;IconvPair g2u("utf-8", "gb2312");char array[pageSize] = {'a'};const char *inArray = array;size_t inArrayLen = pageSize;size_t ret = g2u.convert(&inArray, &inArrayLen);CPPUNIT_ASSERT((0 == ret) && ((pageSize * 2) == g2u.bufferLen()));char *buffer = reinterpret_cast<char*>(malloc(1024 * 1024 * sizeof(char)));CPPUNIT_ASSERT(NULL != buffer);FILE *f = fopen("league2012b.htm", "r");CPPUNIT_ASSERT(NULL != f);size_t fileLen = 0;while (!feof(f)){fileLen += fread(buffer + fileLen, 1, pageSize, f);}fclose(f);const char *bufferIn = buffer;ret = g2u.convert(&bufferIn, &fileLen);CPPUNIT_ASSERT(0 == ret);f = fopen("league2012b.txt", "w");CPPUNIT_ASSERT(NULL != f);fwrite(g2u.buffer(), 1, g2u.contentLen(), f);fclose(f);free(buffer);
}

由于直接将测试代码块中的league2012b.htm复制到CSDN的代码块中会有问题,所以只好请大家直接用快盘共享出来的链接自己下载了。链接地址如下

http://www.kuaipan.cn/file/id_19631556775674797.htm

正确的iconv使用方法相关推荐

  1. 接口里面的方法都是抽象方法吗_正确的敷面膜方法 你真的都掌握了吗

    正确的敷面膜方法,你真的都掌握了吗,一定要把握好敷面膜的最佳时间哟. 1.迪蕾玻尿酸保湿补水面膜 25ml*5 ¥90 采用日本384全球最薄蚕丝膜布,蕴含超小分子玻尿酸,比普通玻尿酸分子更容易渗透肌 ...

  2. acegis连接使用方法_正确打开效果器 连接方法和使用技巧必须要知道

    原标题:正确打开效果器 连接方法和使用技巧必须要知道 效果器是一种提供各种声场效果,并对声音信号在时间和频率等多方面多方位进行加工处理以产生特殊音响效果的周边设备,它广泛使用在电台.电视台的节目制作上 ...

  3. Py之easygui:easygui的简介、安装(最正确安装)、使用方法之详细攻略

    Py之easygui:easygui的简介.安装(最正确安装).使用方法之详细攻略 目录 easygui的简介 easygui安装 1.获取Python的工具包easygui 2.easygui安装 ...

  4. php输出楼层号,ZBlog开发中实现评论楼层号正确输出的具体方法代码

    在官方的wiki中,针对评论部分的标签调用是集成了评论楼号的,即标签{$comment.FloorID}.这个标签是不计算子评论的,所以并不是采用key直接计算出的楼号.经过测试,我们会发现,这个楼号 ...

  5. 试图加载格式不正确的程序 解决方法

    试图加载格式不正确的程序 解决方法 参考文章: (1)试图加载格式不正确的程序 解决方法 (2)https://www.cnblogs.com/94cool/archive/2012/11/06/27 ...

  6. 卓训教育:如何批评孩子,正确批评孩子的方法

    孩子犯错都应该受到批评,但严格的教育并不是意味着劈头盖脸骂孩子一顿,错误的教育方式不仅不能让孩子进步,反而会让他们更加自卑或者叛逆.那么,家长如何批评孩子,正确批评孩子的方法有哪些呢? 孩子在成长过程 ...

  7. PS中添加插件 无法加载扩展,未经正确签署的解决方法

    为什么会出现PS无法加载扩展,未经正确签署的解决方法 因为PS没有在注册表中注册 我们如何解决呢? 打开注册表 添加字符串 这样就行了

  8. 苹果和安卓正确的卸载软件方法分享

    平时我们的手机都会安装很多软件,用了一段时间之后发现不好用,有些人直接在桌面上就给删了,今天就来教你正确卸载软件的方法,彻底清理手机的垃圾. 错误卸载方式 首先相信大部分人卸载手机软件,都是直接在桌面 ...

  9. win10计算机未连接到网络适配器,win10未检测到正确的适配器怎么办_win10检测不到正确的适配器解决方法...

    有的用户在使用win10系统的电脑时可能会遇到电脑提示未检测到正确的适配器的情况,应该有许多用户不知道该怎么办,那么win10未检测到正确的适配器怎么办?遇到这个情况可能是电脑缺少网卡驱动,下面我们就 ...

最新文章

  1. 用mpvue实现的微信小程序版cnode社区
  2. Samba远程代码执行漏洞(CVE-2017-7494)复现
  3. “哪吒”出世!华为开源中文版BERT模型
  4. 【做题】uoj#370滑稽树上滑稽果——巧妙dp
  5. 2017.10.27 sue的小球 失败总结
  6. java基础覆盖——知识库搭建-1
  7. java spring异常处理_Spring项目中优雅的异常处理
  8. 配置机器学习训练环境太麻烦?开源工具Parris说一键就搞定
  9. 备忘: MIRACL 大数运算库使用手册
  10. Git删除本地/本地远程/远程服务器分支
  11. ssl证书不可信 群晖_上海云盾 CDN 网站 SSL 证书过期更新不生效问题排查和解决...
  12. erf函数 matlab,关于ODE45初值问题和erf函数的问题
  13. eclipse默认指向 WebContent 目录 修改为 webRoot
  14. 一、财务框架与基础知识
  15. NTFS,exFAT,FAT32最详细的评测
  16. 6个适合成年人的自学网站,每天半小时改变你一生
  17. Weighted Boxes Fusion加权检测框合并
  18. SHAP可解释工具的理解及应用
  19. 说说jvm什么时候会回收垃圾
  20. 系统,工具,源码,语言组成的数字世界-2021-

热门文章

  1. exec 和 exec_
  2. 本源量子与德美牵头成立产业联盟,生物化学正式进入量子计算“赛道”|现场专访
  3. 【Druid】(八)Apache Druid 核心插件 Kafka Indexing Service SLS Indexing Service
  4. 法律法规与标准化知识
  5. python打印七段数码管引脚图_前辈学51单片机的感悟是怎么样的?说说看
  6. 酷炫命令行背景图操作步骤
  7. 机器人门禁控制盒怎么接线方法_门禁控制器怎么接线_门禁控制器接线图说明 - 全文...
  8. FL Studio乐理教程之调式音阶
  9. 解决在使用wandb时出现SSLError的思路
  10. nginx完全卸载删除