中国IT动力,最新最全的IT技术教程
最新100篇 | 推荐100篇 | 专题100篇 | 排行榜 | 搜索 | 在线API文档
首 页 | 程序开发 | 操作系统 | 软件应用 | 图形图象 | 网络应用 | 精文荟萃 | 教育认证 | 硬件维护 | 未整理篇 | 站长教程
ASP JS PHP工程 ASP.NET 网站建设 UML J2EESUN .NET VC VB VFP 网络维护 数据库 DB2 SQL2000 Oracle Mysql
服务器 Win2000 Office C DreamWeaver FireWorks Flash PhotoShop 上网宝典 CorelDraw 协议大全 网络安全 微软认证
硬件维护  CPU  主板  硬盘  内存  显卡  显示器  键盘鼠标  声卡音箱  打印机  机箱电源  BIOS  网卡  C#  Java  Delphi  vs.net2005
  当前位置:> 程序开发 > 编程语言 > C/C++
请教iconv函数的使用
作者:未知 时间:2005-09-13 19:22 出处:ChinaUnix.net 责编:chinaitpower
              摘要:请教iconv函数的使用

在SOLARIS下装了个libiconv库,编译以下程序为:
gcc -L/usr/local/iconv/lib -o conv conv.c -liconv
#include "/usr/local/iconv/include/iconv.h"
#include <strings.h>
#define BUFLEN 200

char inbuf[BUFLEN];
char outbuf[BUFLEN];
char* pin = inbuf;
char* pout = outbuf;
int inlen;
int outlen = BUFLEN;


main(int argc, char **argv)
{
 iconv_t cd;
 ssize_t n;

 bzero(inbuf, BUFLEN);
 strncpy(inbuf, argv[1], BUFLEN);

 if((cd = iconv_open(argv[3], argv[2])) == (iconv_t)-1) //argv2 = from, argv3 =to
       return;
printf("convsing.........\n");
       inlen = strlen(inbuf);
printf("cd is %d, inlen = %d\n", cd, inlen);

if((n = iconv(cd, (const char **)&pin, &inlen, &pout, &outlen))  ==  (ssize_t)(-
1)){
       perror("iconv error\n");
       return;
}

 printf("Output: %s,n= %d,inlen=%d,outlen=%d\n", pout,n,inlen,outlen);
 iconv_close(cd);
}
运行:
./conv 测试 GB2312 UTF-8
convsing.........
cd is 134864, inlen = 4
Output: ,n= 0,inlen=0,outlen=194
既然iconv()也没出错,而且inlen已经-为0,说明已经作过转换了,为什么n=0,pout没有内容输出呢?

 bigluo 回复于:2003-06-08 12:16:58
我对solaris不是很熟悉,但是在linux中,iconv的正确转换需要glibc有相应的码表的支持。你可以检查一下你的solaris中的libc有gb2312->utf8的码表吗?

 chdonald 回复于:2003-06-08 15:16:51
我查过了,支持的
iconv -l
而且用它提供的iconv命令也可以正确把一个GB2312文件的内容转换成UTF-8的

 bigluo 回复于:2003-06-08 15:57:19
我在三年前在RH linux 6.2下做过这些,现在真的记得不是特别清楚了,当时是根据台湾cle网站上的中文化文章做的,那儿对宽字节和iconv讲的很清楚,你可以去查阅一下。

 gadfly 回复于:2003-06-08 23:14:33
是这样子的。

iconv的man有点问题。iconv返回的实际上不是成功的数目。0只是说明成功。

最好先bzero outbuf, 另外,转化的不一定是可打印字符,你可以打印字符串的ascii码看看。

 libad 回复于:2003-06-10 17:03:24
我在LDAP中配置了中文,在solaris下面用C取出后是乱码。
gadfly说让我到这来请教各位。

1)我solaris下面没有装libiconv库。
应该去那里找这个库来安装?

2)听bigluo说:
iconv的正确转换需要glibc有相应的码表的支持。你可以检查一下你的solaris中的libc有gb2312->utf8的码表吗? 

我运行:
      iconv -f UTF-8 -t GB2312 my.txt
提示:
       不支持到 GB2312 的 UTF-8

好象是没有相应的码表,我应该怎么办,去那里去安装呀?

 gadfly 回复于:2003-06-10 18:04:45
1.需要装glibc-devel软件包

2.我的solaris装了这几个包
ALE         SUNWciu8             Simplified Chinese (EUC) iconv modules for UTF-8
ALE         SUNWciu8x            Simplified Chinese (EUC) iconv modules for UTF-8 (64-bit)
ALE         SUNWhiu8             Traditional Chinese iconv modules for UTF-8
ALE         SUNWhiu8x            Traditional Chinese (EUC) iconv modules for UTF-8 (64-bit)

另外这样是可以的
iconv -f UTF-8 -t gb2312 my.txt

 libad 回复于:2003-06-10 18:11:34
斑竹:

glibc-devel软件包 去那里下载呀?

 gadfly 回复于:2003-06-10 18:38:22
哦,在solaris上有个单独的libiconv

sunfreeware.com

 chdonald 回复于:2003-06-10 20:06:30
没错,我就是下了这个包的。可是我的问题还没搞定,请大家帮忙!!

 gadfly 回复于:2003-06-10 22:40:37
你现在做到哪一步出问题了?

 gadfly 回复于:2003-06-10 23:40:40
我有稍微看了chdonald的代码发现最后printf有问题,pout在iconv会指向转换结束的位置,当然什么都没有打印。我稍微改了一下。你们自己测试看看。
我这边现在没法在终端输入中文。可以这样测试
./test_iconv 字符 gb2312 -t UTF-8
iconv -f gb2312 -t UTF-8 ccc
ccc内容
[code:1:07e2cc8cfb]
字符
[/code:1:07e2cc8cfb]
看看两个结果是否一样,然后对输出的串做反变换看看
[code:1:07e2cc8cfb]
/* gcc test_iconv -o test_iconv */
#include <stdio.h>
#include <iconv.h>
#define BUFLEN 200

char inbuf[BUFLEN];
char outbuf[BUFLEN];
char* pin = inbuf;
char* pout = outbuf;
int inlen;
int outlen = BUFLEN - 1;


void outbin(char * outbuf) {
        char *p = outbuf;
        if (!p)  return;
        while (*p) printf("%c", *p++);

        printf("\n");
}

void usage(const char * prog) {
        printf("Usage: %s string from_code to_code\n", basename(prog));
        exit(-1);
}

int main(int argc, char **argv) {
        iconv_t cd;

        if (argc < 4) usage(argv[0]);

        bzero(inbuf, 0, BUFLEN);
        bzero(outbuf, 0, BUFLEN);
        strncpy(inbuf, argv[1], BUFLEN);

        if((cd = iconv_open(argv[3], argv[2])) < 0) return -1;

        inlen = strlen(inbuf);
        printf("inlen = %d, %s, pout addr is %p\n", inlen, inbuf, pout);
        inlen++;
  //      iconv(cd, NULL, NULL, NULL, NULL);
        if(iconv(cd, &pin, &inlen, &pout, &outlen) < 0)
                return;
 
        printf("outlen is %d, pout addr is %p, Output: %s\n", outlen, pout, outbuf);
//      outbin(outbuf);
        iconv_close(cd);
        return 0;
}
[/code:1:07e2cc8cfb]

 libad 回复于:2003-06-11 10:17:33
我去sunfreeware.com 下载了 libiconv-1.6.1-sol8-sparc-local

怎么安装呀?

 gadfly 回复于:2003-06-11 11:50:36
pkgadd -d libiconv*

 chdonald 回复于:2003-06-11 20:59:21
是的,iconv返回0就说明字符序列全部已经转换成功,pin和pout指针都会变化的。
以下是例子:
[code:1:546c0e288d]     #include <stdio.h>
     #include <errno.h>
     #include <string.h>
     #include <iconv.h>
     #include <stdlib.h>


     /*
      * For state-dependent encodings, changes the state of the conversion
      * descriptor to initial shift state.  Also, outputs the byte sequence
      * to change the state to initial state.
      * This code is assuming the iconv call for initializing the state
      * won't fail due to lack of space in the output buffer.
      */
     #define INIT_SHIFT_STATE(cd, fptr, ileft, tptr, oleft) \
         { \
             fptr = NULL; \
             ileft = 0; \
             tptr = to; \
             oleft = BUFSIZ; \
             (void) iconv(cd, &fptr, &ileft, &tptr, &oleft); \
             (void) fwrite(to, 1, BUFSIZ - oleft, stdout); \
         } 

     int
     main(int argc, char **argv)
     {
         iconv_t cd;
         char    from[BUFSIZ], to[BUFSIZ];
         char    *from_code, *to_code;
         char    *tptr;
         const char  *fptr;
         size_t  ileft, oleft, num, ret;

         if (argc != 3) {
             (void) fprintf(stderr,
                 "Usage: %s from_codeset to_codeset\\n", argv[0]);
             return (1);
         }

         from_code = argv[1];
         to_code = argv[2];

         cd = iconv_open((const char *)to_code, (const char *)from_code);
         if (cd == (iconv_t)-1) {
             /*
              * iconv_open failed
              */
             (void) fprintf(stderr,
                 "iconv_open(%s, %s) failed\\n", to_code, from_code);
             return (1);
         }

         ileft = 0;
         while ((ileft +=
             (num = fread(from + ileft, 1, BUFSIZ - ileft, stdin))) > 0) {
             if (num == 0) {
                 /*


                  * Input buffer still contains incomplete character
                  * or sequence.  However, no more input character.
                  */

                 /*
                  * Initializes the conversion descriptor and outputs
                  * the sequence to change the state to initial state.
                  */
                 INIT_SHIFT_STATE(cd, fptr, ileft, tptr, oleft);
                 (void) iconv_close(cd);

                 (void) fprintf(stderr, "Conversion error\\n");
                 return (1);
             }

             fptr = from;
             for (;;) {
                 tptr = to;
                 oleft = BUFSIZ;

                 ret = iconv(cd, &fptr, &ileft, &tptr, &oleft);
                 if (ret != (size_t)-1) {
                     /*
                      * iconv succeeded
                      */

                     /*
                      * Outputs converted characters
                      */
                     (void) fwrite(to, 1, BUFSIZ - oleft, stdout);
                     break;
                 }

                 /*
                  * iconv failed
                  */
                 if (errno == EINVAL) {
                     /*
                    * Incomplete character or shift sequence
                      */

                     /*
                      * Outputs converted characters
                      */
                     (void) fwrite(to, 1, BUFSIZ - oleft, stdout);
                     /*
                      * Copies remaining characters in input buffer
                      * to the top of the input buffer.
                      */
                     (void) memmove(from, fptr, ileft);
                     /*
                      * Tries to fill input buffer from stdin

                      */
                     break;
                 } else if (errno == E2BIG) {
                     /*
                      * Lack of space in output buffer
                      */

                     /*
                      * Outputs converted characters
                      */
                     (void) fwrite(to, 1, BUFSIZ - oleft, stdout);
                     /*
                      * Tries to convert remaining characters in
                      * input buffer with emptied output buffer
                      */
                     continue;
                 } else if (errno == EILSEQ) {
                     /*
                      * Illegal character or shift sequence
                      */

                     /*
                      * Outputs converted characters
                      */
                     (void) fwrite(to, 1, BUFSIZ - oleft, stdout);
                     /*
                      * Initializes the conversion descriptor and
                      * outputs the sequence to change the state to
                      * initial state.
                      */
                     INIT_SHIFT_STATE(cd, fptr, ileft, tptr, oleft);
                     (void) iconv_close(cd);

                     (void) fprintf(stderr,
                      "Illegal character or sequence\\n");
                     return (1);
                 } else if (errno == EBADF) {
                     /*
                      * Invalid conversion descriptor.
                      * Actually, this hud''''t happen here.
                      */
                     (void) fprintf(stderr, "Conversion error\\n");
                     return (1);
                 } else {
                     /*
                      * This errno is not defined
                      */
                     (void) fprintf(stderr, "iconv error\\n");
                     return (1);
                 }
             }
         }


         /*
          * Initializes the conversion descriptor and outputs
          * the sequence to change the state to initial state.
          */
         INIT_SHIFT_STATE(cd, fptr, ileft, tptr, oleft);

         (void) iconv_close(cd);
         return (0);
     }[/code:1:546c0e288d]

关闭本页
 
首页 | 投资与合作 | 服务条款 | 隐私政策 | 收藏本站 | 设为首页 | 新用户注册 | 免责声明 | 使用帮助
Copyright ©2005-2008 chinaitpower.com All rights reserved. www.chinaitpower.com 版权所有