Chinaunix

标题: 再请教一个问题,关于iconv的,返回失败,但转换成功了,不知道原因。 [打印本页]

作者: rain_fish    时间: 2010-11-29 14:22
标题: 再请教一个问题,关于iconv的,返回失败,但转换成功了,不知道原因。
下面是代码,转化成功了,但iconv返回-1,errno为84,errno.84 is: Invalid or incomplete multibyte or wide character
不知道原因,请高手指点。
  1. #include <iconv.h>
  2. #include <string.h>
  3. #include <stdlib.h>
  4. #include <stdio.h>
  5. #include <errno.h>
  6. #define OUTLEN 255
  7. //代码转换:从一种编码转为另一种编码
  8. int code_convert(char *from_charset,char *to_charset,char *inbuf,int inlen,char *outbuf,int outlen)
  9. {
  10. iconv_t cd;
  11. int rc;
  12. char **pin = &inbuf;
  13. char **pout = &outbuf;

  14. cd = iconv_open(to_charset,from_charset);
  15. if (cd==0) return -1;
  16. memset(outbuf,0,outlen);
  17. if (iconv(cd,pin,(size_t*)&inlen,pout,(size_t*)&outlen)==-1) return -1;
  18. iconv_close(cd);
  19. return 0;
  20. }
  21. //UNICODE码转为GB2312码
  22. int u2g(char *inbuf,int inlen,char *outbuf,int outlen)
  23. {
  24. return code_convert("utf-8","gb2312",inbuf,inlen,outbuf,outlen);
  25. }
  26. //GB2312码转为UNICODE码
  27. int g2u(char *inbuf,size_t inlen,char *outbuf,size_t outlen)
  28. {
  29. return code_convert("gb2312","utf-8",inbuf,inlen,outbuf,outlen);
  30. }

  31. main()
  32. {
  33. char *in_utf8 = "姝e?ㄥ??瑁?";
  34. char *in_gb2312 = "正在安装";
  35. char out[OUTLEN];

  36. //unicode码转为gb2312码
  37. int rc = u2g(in_utf8,strlen(in_utf8),out,OUTLEN);
  38. printf("rc:%d, errno:%d, unicode-->gb2312 out=%sn",rc,errno, out);
  39. //gb2312码转为unicode码
  40. rc = g2u(in_gb2312,strlen(in_gb2312),out,OUTLEN);
  41. printf("rc:%d, errno:%d, gb2312-->unicode out=%sn",rc,errno,out);
  42. }
复制代码

作者: lj56630325    时间: 2010-11-29 15:11
本帖最后由 lj56630325 于 2010-11-29 15:13 编辑

export info in bash:

  1. declare -x LANG="zh_CN.utf8"
  2. declare -x LC_ALL=""
  3. declare -x LC_CTYPE="zh_CN.utf8"
复制代码
我的main, 其他一样.

  1. main()
  2. {
  3.     char *in_utf8 = "正在安装"; //
  4.     char out[OUTLEN];
  5.     char out_gb2312[OUTLEN];

  6.     //unicode码转为gb2312码
  7.     int rc = u2g(in_utf8,strlen(in_utf8),out,OUTLEN);
  8.     printf("rc:%d, errno:%d, unicode-->gb2312 out=%s\n",rc,errno, out);                                               
  9.     //gb2312码转为unicode码
  10.     rc = g2u(out,strlen(out),out_gb2312,OUTLEN);
  11.     printf("rc:%d, errno:%d, gb2312-->unicode out=%s\n",rc,errno,out_gb2312);                                         
  12. }

复制代码

作者: lj56630325    时间: 2010-11-29 15:13
输出

  1. rc:0, errno:0, unicode-->gb2312 out=
  2. rc:0, errno:0, gb2312-->unicode out=正在安装
复制代码
可能你的"正在安装"不是gb2312
作者: rain_fish    时间: 2010-11-29 16:11
输出可能你的"正在安装"不是gb2312
lj56630325 发表于 2010-11-29 15:13



    非常感谢您的回答,我按照您的代码试了一下还是不行:
rc:-1, errno:84, unicode-->gb2312 out=���ڰ�װ
rc:-1, errno:84, gb2312-->unicode out=正在安装
通过gdb,发现第一行输出地确实是gbk编码,我的终端是utf8编码的,所以第二行可以看到。
而且文件格式我是通过iconv改变成utf8的,
[user@localhost1 test]$ file 4.c
4.c: UTF-8 Unicode C program text

也是utf8,输出还是有问题,请再次指教。。。。
作者: rain_fish    时间: 2010-11-29 16:32
输出可能你的"正在安装"不是gb2312
lj56630325 发表于 2010-11-29 15:13



    您好,您运行的代码就是我放在上面的代码吗?
作者: rain_fish    时间: 2010-11-29 16:46
关键是虽然返回成功,但是却转换成功了。。。,很是纳闷。。。
作者: lj56630325    时间: 2010-11-29 17:29
回复 5# rain_fish
1) 我用的代码是2楼贴的代码.

2) 我确定的是我程序中的"正在安装"是UTF8的. (我的BASH是UTF8的, 我手动输入的"正在安装")

3) 你应该检测你程序的字符是什么编码的. 这个跟文件(4.c: UTF-8 Unicode C program text)是UTF8有没有关系, 我不清楚.
作者: zylthinking    时间: 2010-11-30 12:29
关键是虽然返回成功,但是却转换成功了。。。,很是纳闷。。。
rain_fish 发表于 2010-11-29 16:46



很可能是你的多字节字符串最后一个字符是不完整的,所谓转换成功, 大概是之前的转换成功了, 而后面跟着错误不可见的半个字符
作者: rain_fish    时间: 2010-11-30 13:44
很可能是你的多字节字符串最后一个字符是不完整的,所谓转换成功, 大概是之前的转换成功了, 而后面 ...
zylthinking 发表于 2010-11-30 12:29



    我确定后没有不完整的字符,很是纳闷,刚才在虚拟机上测试了一下,竟然成功。不知道是什么原因了
作者: zylthinking    时间: 2010-11-30 15:44
我确定后没有不完整的字符,很是纳闷,刚才在虚拟机上测试了一下,竟然成功。不知道是什么原因了
rain_fish 发表于 2010-11-30 13:44



淡定, 淡定。。。。。。。。{:3_189:}
作者: rain_fish    时间: 2010-11-30 18:00
问题原因找到,是由于size_t在32位和64位机上字节数不同所致!
作者: rain_fish    时间: 2011-01-07 13:14
该问题顺利结贴了。
作者: jack1219    时间: 2012-08-24 14:08
那LZ最后代码怎么改的啊?
作者: fiendcly    时间: 2012-08-24 20:26
本帖最后由 fiendcly 于 2012-08-24 20:27 编辑

記得 以前寫 UTF-8 轉 BIG5 的痛苦指數很高....

因為 BIG5 的 編碼範圍 比 UTF-8 小.

所以 BIG5 常會因為編碼範圍的問題讓 ICONV 報錯...

我記得我當時的解法是 遇到 ICONV 出錯停下來時我就會 走 遞回 把 停在出錯的字元上的 字元轉成 UNICODE HTML &#XX;

再接下去把 UTF-8 下面要轉的重新接上來.

我也被 ICONV 折磨過~>_<"


作者: lc-soft    时间: 2012-08-25 11:35
本帖最后由 lc-soft 于 2012-08-25 11:36 编辑

回复 14# fiendcly
居然挖坟。。。

刚进帖发现LZ的代码好眼熟,原来我之前搞编码转换也复制粘贴了这代码,但现在已经改用其它方式实现了。
据说标准库自带编码转换函数。

   
作者: llol63    时间: 2017-04-18 08:34
我也遇到了楼主的问题,确实是长度类型问题,把int转成size_t传入iconv函数时导致长度不对,应该加个临时变量存储。
int CodeConvert(char *psFromCharset,char *psToCharset,char *psInputBuf,int iInputLen,char*psOutputBuf,int iOutputlen)  
{  
        iconv_t iConvHandle;   
        char **pInput = &psInputBuf;  
        char **pOutput = &psOutputBuf;  
        size_t inLen = iInputLen;
        size_t outLen = iOutputlen;
       
        iConvHandle = iconv_open(psToCharset,psFromCharset);  
        if (iConvHandle == 0)
        {
                fprintf(stderr, "iconv_open Error[%s]!",strerror(errno));       
                return -1;
        }
          
        if (iconv(iConvHandle,pInput,&inLen,pOutput,&outLen) == -1)
        {
                fprintf(stderr, "iconv Error[%s]!",strerror(errno));
                iconv_close(iConvHandle);
                return -1;  
        }
       
        iconv_close(iConvHandle);  
        return 0;  
}
作者: 潜水一厮    时间: 2017-06-07 11:18
提示: 作者被禁止或删除 内容自动屏蔽




欢迎光临 Chinaunix (http://bbs.chinaunix.net/) Powered by Discuz! X3.2