在代码中遇到需要将不同编码进行转换的问题,同事提示使用iconv函数来实现转换,自己就查了一下函数介绍开始使用,本以为很简单的函数调用即可,中间却出了一个小小的问题,记录一下,学习之
自定义函数对转换函数的封装
1 // 对系统iconv进行包装的函数
2 int scsIconv(string &strSou, string &strDest)
3 {
4 // 初始化转换函数
5 iconv_t hIconv =
6 iconv_open(g_strDestCharSet.c_str(), g_strSouCharSet.c_str());
7 if (hIconv == (iconv_t)-1)
8 {
9 return -1;
10 }
11
12 // 获取源数据
13 size_t nSouSize = strSou.size();
14 char *pcInBuf = (char*)malloc(strSou.size() + 1);
15 memset(pcInBuf, 0, strSou.size() + 1);
16 memcpy(pcInBuf, strSou.c_str(), strSou.size());
17 char *pcIn = pcInBuf;
18
19 // 开辟目的存储空间
20 size_t nDestSize = TRANS_OUT_BUF_DEF_SIZE > 2 * nSouSize ?
21 TRANS_OUT_BUF_DEF_SIZE : 2 * nSouSize;
22 char *pcOutBuf = (char*)malloc(nDestSize);
23 if (!pcOutBuf)
24 {
25 free(pcInBuf);
26 return -1;
27 }
28 char *pcOut = pcOutBuf;
29
30 // 开始转换
31 size_t nRet;
32 do
33 {
34 memset(pcOutBuf, 0, nDestSize);
35 nRet = iconv(hIconv, &pcIn, &nSouSize, &pcOut, &nDestSize);
36 if (nRet == (size_t)-1)
37 {
38 if (errno == E2BIG)
39 {
40 pcOutBuf = (char*)realloc(pcOutBuf, 2 * nDestSize);
41 if (!pcOutBuf)
42 {
43 free(pcInBuf);
44 return -1;
45 }
46 pcIn = pcInBuf;
47 pcOut = pcOutBuf;
48
49 nDestSize = 2 * nDestSize;
50 }
51 else
52 {
53 free(pcInBuf);
54 return -1;
55 }
56 }
57 else
58 {
59 strDest = pcOutBuf;
60 break;
61 }
62 }while (1);
63
64 free(pcInBuf);
65 free(pcOutBuf);
66 return 0;
67 }
那个小小的问题就出在iconv对源数据地址和目的数据地址的处理上,iconv执行之后对修改源数据地址和目的数据地址,简单来说就是,在iconv中会一步一步的向后移动这两个指针的指向位置,当转换结束后,均指向各自缓冲区的结尾处,因此取数据时需要注意。应该将原来的目的地址拷贝一份,以用在转换后取数据。
下面是我调试时的信息
图片中用红线圈起来的值体现了上面所说的iconv对源地址和目的地址的具体修改,
执行iconv后的pcIn和执行前的pcIn相差的值正好等于nSouSize的大小即源数据的字节数86。
执行iconv后的pcOut和执行前的pcOut相差值正好等于nDestSize前后的差值为90。
这里的90和86是因为转换中只有4个中文字符,所以,长度增加了4。