libiconv 下载
网站链接:
https://savannah.gnu.org/projects/libiconv/
http://www.gnu.org/software/libiconv/
iconv函数
/* Convert at most *INBYTESLEFT bytes from *INBUF according to the
code conversion algorithm specified by CD and place up to
*OUTBYTESLEFT bytes in buffer at *OUTBUF. */
extern size_t iconv (iconv_t __cd, char **__restrict __inbuf,
size_t *__restrict __inbytesleft,
char **__restrict __outbuf,
size_t *__restrict __outbytesleft);
注意函数参数 __inbuf
与 __outbuf
为 二级指针, __inbytesleft
与 __outbytesleft
是指针
函数执行后,无论是否转换成功,这四个参数的值要发生变化。它们即是输入参数也输出参数,但是意思不同。
作为入参:
第一个参数 cd
是转换句柄。
第二个参数 __inbuf
是输入字符串的地址的地址。
第三个参数 __inbytesleft
是输入字符串的长度。
第四个参数 __outbuf
是输出缓冲区的首地址
第五个参数 __outbytesleft
是输出缓冲区的长度。
作为出参
第一个参数 cd
是转换句柄。
第二个参数 __inbuf
指向剩余字符串的地址的地址。
第三个参数 __inbytesleft
是剩余字符串的长度。
第四个参数 __outbuf
是输出缓冲区剩余空间的首地址的地址 。
第五个参数 __outbytesleft
是输出缓冲区剩余空间的长度。
示例代码:
#include <iostream>
#include <iconv.h>
#include <cstring>
#include <fstream>
class CodeConverter {
private:
iconv_t cd;
public:
// 构造 from_ 原编码 to_ 目标编码
CodeConverter(const char *from_,const char *to_) {
cd = iconv_open(to_, from_);
}
// 析构
~CodeConverter() {
iconv_close(cd);
}
// 转换输出
/**
* 转换编码
* @param inbuf 待转原数据
* @param inlen 待转原数据长度
* @param outbuf 转换后数据
* @param outlen 转换后长度
* @return
*/
int convert(char *inbuf,int inlen,char *outbuf,int outlen) {
char **pin = &inbuf;
char **pout = &outbuf;
memset(outbuf,0,outlen);
/**作为入参
第一个参数 cd 是转换句柄。
第二个参数 pin 是输入字符串的地址的地址。
第三个参数 inlen 是输入字符串的长度。
第四个参数 pout 是输出缓冲区的首地址的地址
第五个参数 outlen 是输出缓冲区的长度。
*/
std::cout << "Before..." << std::endl;
printf("pin = %p\n",pin);
printf("pout = %p\n",pout);
printf("inbuf = %p\n",inbuf);
printf("outbuf = %p\n",outbuf);
printf("inlen = %d\n",inlen);
printf("outlen = %d\n",outlen);
int ret = iconv(cd, pin, (size_t *)&inlen, pout, (size_t *)&outlen);
std::cout << "After..." << std::endl;
printf("pin = %p\n",pin);
printf("pout = %p\n",pout);
printf("inbuf = %p\n",inbuf);
printf("outbuf = %p\n",outbuf);
printf("inlen = %d\n",inlen);
printf("outlen = %d\n",outlen);
/**作为出参
第一个参数 cd 是转换句柄。
第二个参数 pin 指向剩余字符串的地址的地址。 注意 剩余字符串的地址
第三个参数 inlen 是剩余字符串的长度。 注意 剩余字符串长度
第四个参数 pout 是输出缓冲区剩余空间的首地址的地址 注意 缓冲区剩余空间的首地址
第五个参数 outlen 是输出缓冲区剩余空间的长度。 注意 缓冲区剩余空间的长度
*/
return ret;
}
};
int main() {
std::cout << "Hello, World!" << std::endl;
std::ifstream inFile;
inFile.open("../test");
int dataLen = 128;
auto dataArray = new char[dataLen];
inFile.read(reinterpret_cast<char *>(dataArray), dataLen );
inFile.close();
std::cout << "dataArray = " << dataArray << std::endl;
std::cout << "strlen(dataArray) = " << strlen(dataArray) << std::endl;
// gb2312-->utf-8
CodeConverter cc = CodeConverter("gb2312","utf-8");
int len = strlen(dataArray);
char bufin[len+4];
memset(bufin,0,len+4);
for (int j = 0; j < len; ++j) {
bufin[j] = dataArray[j];
}
int bufsize = 256;
char bufout[bufsize];
memset(bufout,0,bufsize);
printf("bufin size = %d\n",len+4);
printf("bufin = %p\n",bufin);
printf("bufout = %p\n",bufout);
int ret = cc.convert(bufin,len+4,bufout,bufsize);
std::cout << "bufout = " << bufout << std::endl;
std::cout << "strlen(bufout) = " <<strlen(bufout) << std::endl;
delete []dataArray;
return 0;
}
如图可发现
inbuf: 0x9620 + 14 = 0x962C , cc.convert(bufin,len+4,bufout,bufsize) 传入的是 len+4
outbuf: 0x9520 + 12 + 4 = 0x9530
所以值得注意的是,如果在堆上分配的空间直接调用iconv原函数(不封装)处理后,由于iconv会改变那几个参数的值,在释放前要提前保存分配的地址。
希望我的文章对于大家有帮助,由于个人能力的局限性,文中可能存在一些问题,欢迎指正、补充!