iconv是一个字符集转换函数,原型为:

size_t iconv(iconv_t cd,

             char **inbuf, size_t *inbytesleft,

             char **outbuf, size_t *outbytesleft);

// 传递给do_convert的in_buf,所有字节数(in_buf_size指定)都是可以转换成功的
static int do_convert(iconv_t cd, const char* from, size_t from_size, std::string* to)
{
char* in_buf_ptr = const_cast<char*>(from);
size_t in_bytes_left = from_size;
size_t out_bytes = in_bytes_left*3 + 1;
size_t out_bytes_left = out_bytes;
std::string out(out_bytes_left, '\0');
char* out_buf_start = const_cast<char*>(out.c_str());
char* out_buf_ptr = out_buf_start; int bytes = iconv(cd, &in_buf_ptr, &in_bytes_left, &out_buf_ptr, &out_bytes_left);
if (-1 == bytes)
return errno; to->assign(out_buf_start, out_bytes-out_bytes_left);
return 0;
} // 可忽略不能转换的部分,
// 也可以在结果中保留不能被转换的部分
// 详细实现可以浏览:
// https://github.com/eyjian/mooon/blob/master/common_library/src/utils/charset_utils.cpp
void CCharsetUtils::convert(const std::string& from_charset, const std::string& to_charset,
const std::string& from, std::string* to,
bool ignore_error, bool skip_error) throw (CException)
{
std::string result; // 用来保存处理后的内容
char* in_buf = const_cast<char*>(from.c_str());
size_t in_bytes = from.size(); // 需要处理的总字节数
size_t in_bytes_left = in_bytes; // 剩余的未被处理的字节数
iconv_t cd = iconv_open(to_charset.c_str(), from_charset.c_str()); if ((iconv_t)(-1) == cd)
{
THROW_EXCEPTION(strerror(errno), errno);
}
while (in_bytes_left > 0)
{
int errcode;
size_t out_bytes = in_bytes_left * 3 + 1; // 保证足够大
size_t out_bytes_left = out_bytes;
std::string out(out_bytes_left, '\0');
char* out_buf = const_cast<char*>(out.c_str());
char* out_buf_start = out_buf;
char* in_buf_start = in_buf; // 如果成功,返回值bytes为0
// 如果成功,in_buf指向in的结尾符,即'\0',同时in_bytes_left值为0
// 如果失败,in_buf指向未能转换的起始地址,而in_bytes_left值为剩余的未被转换的(可能含有可转换的)字节数
// 如果成功,则out_bytes-out_bytes_left值为转换后的字节数
// 如果成功,则out_buf_start存储了被转换后的结果,有效长度为out_bytes-out_bytes_left
int bytes = iconv(cd, &in_buf, &in_bytes_left, &out_buf, &out_bytes_left);
if (bytes != -1)
{
result.append(out_buf_start, out_bytes-out_bytes_left);
break;
}
else if (!ignore_error)
{
errcode = errno;
iconv_close(cd);
THROW_EXCEPTION(strerror(errcode), errcode);
}
else
{
// EILSEQ An invalid multibyte sequence has been encountered in the input.
// EINVAL An incomplete multibyte sequence has been encountered in the input.
if ((errno != EINVAL) &&
(errno != EILSEQ))
{
// E2BIG There is not sufficient room at *outbuf.
errcode = errno;
iconv_close(cd);
THROW_EXCEPTION(strerror(errcode), errcode);
}
else
{
// in_buf之前部分是可以转换的
if (in_buf != in_buf_start)
{
std::string str;
errcode = do_convert(cd, in_buf_start, in_buf-in_buf_start, &str);
if (errcode != 0)
{
iconv_close(cd);
THROW_EXCEPTION(strerror(errcode), errcode);
} result.append(str);
} // skip_error决定未能被转换的是否出现在结果当中
if (!skip_error)
{
result.append(in_buf, 1);
} // 往前推进
--in_bytes_left; // 将导致while语句结束
++in_buf;
}
}
} if (-1 == iconv_close(cd))
{
THROW_EXCEPTION(strerror(errno), errno);
} // 不能直接使用to,因为to可能就是from
*to = result;
} void CCharsetUtils::gbk_to_utf8(const std::string& from, std::string* to, bool ignore_error, bool skip_error) throw (CException)
{
convert("gbk", "utf-8", from, to, ignore_error, skip_error);
} void CCharsetUtils::utf8_to_gbk(const std::string& from, std::string* to, bool ignore_error, bool skip_error) throw (CException)
{
convert("utf-8", "gbk", from, to, ignore_error, skip_error);
} void CCharsetUtils::gb2312_to_utf8(const std::string& from, std::string* to, bool ignore_error, bool skip_error) throw (CException)
{
convert("gb2312", "utf-8", from, to, ignore_error, skip_error);
} void CCharsetUtils::utf8_to_gb2312(const std::string& from, std::string* to, bool ignore_error, bool skip_error) throw (CException)
{
convert("utf-8", "gb2312", from, to, ignore_error, skip_error);
}

iconv用法解读的更多相关文章

  1. CMake的含义和用法解读

    什么是 CMake 你或许听过好几种 Make 工具,例如 GNU Make ,QT 的 qmake ,微软的 MS nmake,BSD Make(pmake),Makepp,等等.这些 Make 工 ...

  2. 学习AngularJs:Directive指令用法

    跟我学AngularJs:Directive指令用法解读(上) http://blog.csdn.net/evankaka/article/details/51232895 跟我学AngularJs: ...

  3. const和typedef的常见用法详解

    一.说说const 一般而言,const主要是用来防止定义的对象再次被修改,定义对象变量时要初始化变量. 常见用法如下: 1.用于定义常量变量,这样这个变量在后面就不可以再被修改 const int ...

  4. iconv命令

    iconv 用法: Usage: iconv [OPTION...] [FILE...] Convert encoding of given files from one encoding to an ...

  5. ralitive absolute

    3.relative与absolute的主要区别: 首先,是上面已经提到过的在正常流中的位置存在与否. 其次,relative定位的层总是相对于其最近的父元素,无论其父元素是何种定位方式.如图3: 图 ...

  6. php生成CSV格式(转)

    参考网址: php对csv文件的常用操作集合 http://blog.xhbin.com/archives/748 1,下载CSV格式文档 唯一需要特别注意的是编码. <? include_on ...

  7. Linux下windows中文文本文件乱码问题

    table of content: 乱码问题 用gedit选择正确的字符编码打开文件 文件转码 总结 §乱码 Fedora安装时默认用UTF-8字符编码方式, 这么做有国际化的好处(和很多用utf-8 ...

  8. PHP iconv()编码转换函数用法示例

    PHP iconv()字符编码转换函数的用法,iconv()函数,在php5中是内置的,语法格式:iconv("UTF- 8","GB2312//IGNORE" ...

  9. linux下iconv()函数的用法(转载并修改)

    linux shell 配置文件中默认的字符集编码为UTF-8 .UTF-8是unicode的一种表达方式,gb2312是和unicode都是字符的编码方式,所以说gb2312跟utf-8的概念应该不 ...

随机推荐

  1. 【转】MFC消息处理(一)

    原文网址:http://blog.csdn.net/hyhnoproblem/article/details/6182120 1.MFC窗口如何与AfxWndProc建立联系. 当一个新的CWnd派生 ...

  2. 一个filebeat实例 设置多topic设置

    方法1:一实例多topic: https://discuss.elastic.co/t/filebeat-5-0-output-to-kafka-multiple-topics/67934 The d ...

  3. bzoj 4006 [JLOI2015]管道连接——斯坦纳树

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4006 除了模板,就是记录 ans[ s ] 表示 s 合法的最小代价.合法即保证 s 里同一 ...

  4. 再记录一次delete出错的经历

    调试的时候进行到delete语句时出现问题,我做的操作是在函数体内用int*申请了N个内存空间,这让我十分纳闷,为什么不能delete呢? 回忆到之前delete出错也遇过一次问题 手动封装OpenC ...

  5. sqlite性能优化

    1.数据库性能上 1.1 批量事务插入,提升数据插入的性能 由于sqlite默认每次插入都是事务,需要对文件进行读写,那么减少事务次数就能简书磁盘读写次数从而获得性能提升. 1.2 单条sql优于多条 ...

  6. ROS创建Web代理(Web proxy)给QQ使用HTTP代理

    使用Web代理可以提高网页的访问速度,因为访问的数据会存储在内存或是硬盘中,就会直接从代理服务器中读取.同时,为了提高网络访问的安全性,可以给Web代理服务器设置相应的权限,使它的安全性得到提高. 下 ...

  7. Hive 体系结构

    1.Hive架构与基本组成     下面是Hive的架构图. 图1.1 Hive体系结构     Hive的体系结构可以分为以下几部分:     (1)用户接口主要有三个:CLI,Client 和 W ...

  8. Hive 查看日志

    日志记录了程序运行的过程,是一种查找问题的利器. Hive中的日志分为两种1. 系统日志,记录了hive的运行情况,错误状况.2. Job 日志,记录了Hive 中job的执行的历史过程. 系统日志存 ...

  9. mangle和demangle

    转:https://www.cnblogs.com/robinex/p/7892795.html. mangle和demangle C/C++语言在编译以后,函数的名字会被编译器修改,改成编译器内部的 ...

  10. 解决 ERROR 1045 (28000): Access denied for user 'root'@'localhost' (using password: YES) 问题(转载)

    最近新装好的mysql在进入mysql工具时,总是有错误提示:# mysql -u root -pEnter password:ERROR 1045 (28000): Access denied fo ...