linux下的iconv转码问题

时间:2022-05-05 02:22:36
想用C语言编写xml解析文件,要求把gb2312转为utf-8,使用了linux下的iconv进行转化,但是总是返回-1;无法转码,不知道是那里出问题,请大虾们帮忙,很急!
#include <stdio.h>
#include <stdlib.h>
#include <iconv.h>
#include <string.h>

int main()
{
        iconv_t cd;
        char instr[]="汉字";
        char *inbuf;
        char *outbuf;
        char *outptr;
        unsigned int insize=strlen(instr);
        unsigned int outputbufsize=10;
        unsigned int avail=outputbufsize;
        unsigned int nconv;
        FILE *pf;

        inbuf=instr;
        outbuf=(char *)malloc(outputbufsize);
        outptr=outbuf;
        memset(outbuf,'\0',outputbufsize);

        cd=iconv_open("utf-8","gb2312");    //将字符串编码由gb2312转换为utf-8
        if(cd==(iconv_t)-1)
        {
                printf("fail.\n");
        }
        nconv=iconv(cd,&inbuf,&insize,&outptr,&avail);

        printf("%s\n",outbuf);
        
        
        //write xml file
        
        pf = fopen("test.xml","wb");
if(!pf)
return 0;

strcpy(buf, "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n");
fwrite(buf, 1, strlen(buf), pf);

memset(buf, 0, sizeof(buf));
sprintf(buf, "<Image FileName=\"test.xml\" OCRStatus=\"test\">\n");
fwrite(buf, 1, strlen(buf), pf);

memset(buf, 0, sizeof(buf));
sprintf(buf, "<Return Code =\"%d\">\n",res);
fwrite(buf, 1, strlen(buf), pf);

memset(buf, 0, sizeof(buf));
sprintf(buf,"\t<![CDATA[");
fwrite(buf, 1, strlen(buf), pf);

memset(buf, 0, sizeof(buf));
sprintf(buf,"%s",outbuf);
fwrite(buf, 1, strlen(buf), pf);

memset(buf, 0, sizeof(buf));
sprintf(buf, "\t]]>\n");
fwrite(buf, 1, strlen(buf), pf);

memset(buf, 0, sizeof(buf));
sprintf(buf, "</Return>\n");
fwrite(buf, 1, strlen(buf), pf);
memset(buf, 0, sizeof(buf));
sprintf (buf, "</Image>\n");
fwrite(buf, 1, strlen(buf), pf);


free(outbuf); 
   iconv_close(cd); 
   fclose(pf);

        return 1;
}

14 个解决方案

#1


看起来转换部分没什么问题,你确定你的"汉字"的编码是GB2312吗,可以先把strlen(instr)的值打出来看看,再把输出缓冲增大点看看

#2


是的,“汉字”是GB2312,我把缓冲加大也是一样。

执行nconv=iconv(cd,&inbuf,&insize,&outptr,&avail);
时,
nconv是为-1了

#3


这是我以前写的,可以正常使用,你试试看

int code_convert(char *from_charset,char *to_charset,char *inbuf,size_t inlen,char *outbuf,size_t outlen)
{
    iconv_t cd;
    char **pin = &inbuf;
    char **pout = &outbuf;

    cd = iconv_open(to_charset,from_charset);
    if(cd==0) return -1;

    memset(outbuf,0,outlen);

    if(iconv(cd,pin,&inlen,pout,&outlen)==-1) return -1;

    iconv_close(cd);
    return 0;
}

/*UNICODE码转为GB2312码*/
int u2g(char *inbuf,size_t inlen,char *outbuf,size_t outlen)
{
    return code_convert("utf-8","gb2312",inbuf,inlen,outbuf,outlen);
}

/*GB2312码转为UNICODE码*/
int g2u(char *inbuf,size_t inlen,char *outbuf,size_t outlen)
{
    return code_convert("gb2312","utf-8",inbuf,inlen,outbuf,outlen);
}

#4


我用你这个,也是一样的。返回还是-1

我是在linux red hat 9.0下用gcc编译的。

#5


編譯了你的代碼,可以轉換。只是編譯時有一個警告:

g2u.c:28: warning: passing arg 2 of `libiconv' from incompatible pointer type

將char *inbuf;改為const char *inbuf;後,編譯時無任何警告。

#6


您好,您是在什么环境下编译的?也是红帽子9.0 的gcc编译吗?

#7


大家帮帮忙阿,很急。。。

#8


我是在FreeBSD下編譯的,GCC版本是3.4.6,libiconv版本是1.11。

#9


引用 8 楼 meitolake 的回复:
我是在FreeBSD下編譯的,GCC版本是3.4.6,libiconv版本是1.11。

我的是red hat 9.0,应该可以支持这样的转换吧,怎么老不成功,郁闷阿

#10


你還是應該確認一下源文件的編碼,以保證"汉字"這兩個字為GB2312編碼。
我是將你的這段代碼粘貼在Gedit裡,然後另存為GB2312編碼的文件,再進行編譯。
你是怎麼操作的?

#11


引用 10 楼 meitolake 的回复:
你還是應該確認一下源文件的編碼,以保證"汉字"這兩個字為GB2312編碼。 
我是將你的這段代碼粘貼在Gedit裡,然後另存為GB2312編碼的文件,再進行編譯。 
你是怎麼操作的?

我Gedit另存为 怎么没有可以选择GB2312编码的?小弟对linux不是很熟悉,还望详细说下,谢谢

#12


在Gedit另存窗口下方有一個Character Coding菜單,裡面有一項是Add or Remove...,
點開之後,就可以選擇編碼了。

#13


引用 12 楼 meitolake 的回复:
在Gedit另存窗口下方有一個Character Coding菜單,裡面有一項是Add or Remove..., 
點開之後,就可以選擇編碼了。

收到,真的谢谢你,正如您说的那样是编码问题,“汉字”不是gb2312,在linux下就被转为utf8了,难怪没成功。

#14


哎,我的是在linux PC机上能够转化成功,但是mount到开发板上就傻了,iconv什么也不输出,肿么办啊。。。。iconv需要有什么库编译进文件系统么

#1


看起来转换部分没什么问题,你确定你的"汉字"的编码是GB2312吗,可以先把strlen(instr)的值打出来看看,再把输出缓冲增大点看看

#2


是的,“汉字”是GB2312,我把缓冲加大也是一样。

执行nconv=iconv(cd,&inbuf,&insize,&outptr,&avail);
时,
nconv是为-1了

#3


这是我以前写的,可以正常使用,你试试看

int code_convert(char *from_charset,char *to_charset,char *inbuf,size_t inlen,char *outbuf,size_t outlen)
{
    iconv_t cd;
    char **pin = &inbuf;
    char **pout = &outbuf;

    cd = iconv_open(to_charset,from_charset);
    if(cd==0) return -1;

    memset(outbuf,0,outlen);

    if(iconv(cd,pin,&inlen,pout,&outlen)==-1) return -1;

    iconv_close(cd);
    return 0;
}

/*UNICODE码转为GB2312码*/
int u2g(char *inbuf,size_t inlen,char *outbuf,size_t outlen)
{
    return code_convert("utf-8","gb2312",inbuf,inlen,outbuf,outlen);
}

/*GB2312码转为UNICODE码*/
int g2u(char *inbuf,size_t inlen,char *outbuf,size_t outlen)
{
    return code_convert("gb2312","utf-8",inbuf,inlen,outbuf,outlen);
}

#4


我用你这个,也是一样的。返回还是-1

我是在linux red hat 9.0下用gcc编译的。

#5


編譯了你的代碼,可以轉換。只是編譯時有一個警告:

g2u.c:28: warning: passing arg 2 of `libiconv' from incompatible pointer type

將char *inbuf;改為const char *inbuf;後,編譯時無任何警告。

#6


您好,您是在什么环境下编译的?也是红帽子9.0 的gcc编译吗?

#7


大家帮帮忙阿,很急。。。

#8


我是在FreeBSD下編譯的,GCC版本是3.4.6,libiconv版本是1.11。

#9


引用 8 楼 meitolake 的回复:
我是在FreeBSD下編譯的,GCC版本是3.4.6,libiconv版本是1.11。

我的是red hat 9.0,应该可以支持这样的转换吧,怎么老不成功,郁闷阿

#10


你還是應該確認一下源文件的編碼,以保證"汉字"這兩個字為GB2312編碼。
我是將你的這段代碼粘貼在Gedit裡,然後另存為GB2312編碼的文件,再進行編譯。
你是怎麼操作的?

#11


引用 10 楼 meitolake 的回复:
你還是應該確認一下源文件的編碼,以保證"汉字"這兩個字為GB2312編碼。 
我是將你的這段代碼粘貼在Gedit裡,然後另存為GB2312編碼的文件,再進行編譯。 
你是怎麼操作的?

我Gedit另存为 怎么没有可以选择GB2312编码的?小弟对linux不是很熟悉,还望详细说下,谢谢

#12


在Gedit另存窗口下方有一個Character Coding菜單,裡面有一項是Add or Remove...,
點開之後,就可以選擇編碼了。

#13


引用 12 楼 meitolake 的回复:
在Gedit另存窗口下方有一個Character Coding菜單,裡面有一項是Add or Remove..., 
點開之後,就可以選擇編碼了。

收到,真的谢谢你,正如您说的那样是编码问题,“汉字”不是gb2312,在linux下就被转为utf8了,难怪没成功。

#14


哎,我的是在linux PC机上能够转化成功,但是mount到开发板上就傻了,iconv什么也不输出,肿么办啊。。。。iconv需要有什么库编译进文件系统么