Chinaunix

标题: 请教iconv函数的使用 [打印本页]

作者: chdonald    时间: 2003-06-08 11:53
标题: 请教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
标题: 请教iconv函数的使用
我对solaris不是很熟悉,但是在linux中,iconv的正确转换需要glibc有相应的码表的支持。你可以检查一下你的solaris中的libc有gb2312->;utf8的码表吗?
作者: chdonald    时间: 2003-06-08 15:16
标题: 请教iconv函数的使用
我查过了,支持的
iconv -l
而且用它提供的iconv命令也可以正确把一个GB2312文件的内容转换成UTF-8的
作者: bigluo    时间: 2003-06-08 15:57
标题: 请教iconv函数的使用
我在三年前在RH linux 6.2下做过这些,现在真的记得不是特别清楚了,当时是根据台湾cle网站上的中文化文章做的,那儿对宽字节和iconv讲的很清楚,你可以去查阅一下。
作者: gadfly    时间: 2003-06-08 23:14
标题: 请教iconv函数的使用
是这样子的。

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

最好先bzero outbuf, 另外,转化的不一定是可打印字符,你可以打印字符串的ascii码看看。
作者: libad    时间: 2003-06-10 17:03
标题: 请教iconv函数的使用
我在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
标题: 请教iconv函数的使用
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
标题: 请教iconv函数的使用
斑竹:

glibc-devel软件包 去那里下载呀?
作者: gadfly    时间: 2003-06-10 18:38
标题: 请教iconv函数的使用
哦,在solaris上有个单独的libiconv

sunfreeware.com
作者: chdonald    时间: 2003-06-10 20:06
标题: 请教iconv函数的使用
没错,我就是下了这个包的。可是我的问题还没搞定,请大家帮忙!!
作者: gadfly    时间: 2003-06-10 22:40
标题: 请教iconv函数的使用
你现在做到哪一步出问题了?
作者: gadfly    时间: 2003-06-10 23:40
标题: 请教iconv函数的使用
我有稍微看了chdonald的代码发现最后printf有问题,pout在iconv会指向转换结束的位置,当然什么都没有打印。我稍微改了一下。你们自己测试看看。
我这边现在没法在终端输入中文。可以这样测试
./test_iconv 字符 gb2312 -t UTF-8
iconv -f gb2312 -t UTF-8 ccc
ccc内容

  1. 字符
复制代码

看看两个结果是否一样,然后对输出的串做反变换看看

  1. /* gcc test_iconv -o test_iconv */
  2. #include <stdio.h>;
  3. #include <iconv.h>;
  4. #define BUFLEN 200

  5. char inbuf[BUFLEN];
  6. char outbuf[BUFLEN];
  7. char* pin = inbuf;
  8. char* pout = outbuf;
  9. int inlen;
  10. int outlen = BUFLEN - 1;


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

  15.         printf("\n");
  16. }

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

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

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

  24.         bzero(inbuf, 0, BUFLEN);
  25.         bzero(outbuf, 0, BUFLEN);
  26.         strncpy(inbuf, argv[1], BUFLEN);

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

  28.         inlen = strlen(inbuf);
  29.         printf("inlen = %d, %s, pout addr is %p\n", inlen, inbuf, pout);
  30.         inlen++;
  31.   //      iconv(cd, NULL, NULL, NULL, NULL);
  32.         if(iconv(cd, &pin, &inlen, &pout, &outlen) < 0)
  33.                 return;

  34.         printf("outlen is %d, pout addr is %p, Output: %s\n", outlen, pout, outbuf);
  35. //      outbin(outbuf);
  36.         iconv_close(cd);
  37.         return 0;
  38. }
复制代码

作者: libad    时间: 2003-06-11 10:17
标题: 请教iconv函数的使用
我去sunfreeware.com 下载了 libiconv-1.6.1-sol8-sparc-local

怎么安装呀?
作者: gadfly    时间: 2003-06-11 11:50
标题: 请教iconv函数的使用
pkgadd -d libiconv*
作者: chdonald    时间: 2003-06-11 20:59
标题: 请教iconv函数的使用
是的,iconv返回0就说明字符序列全部已经转换成功,pin和pout指针都会变化的。
以下是例子:
  1.      #include <stdio.h>;
  2.      #include <errno.h>;
  3.      #include <string.h>;
  4.      #include <iconv.h>;
  5.      #include <stdlib.h>;


  6.      /*
  7.       * For state-dependent encodings, changes the state of the conversion
  8.       * descriptor to initial shift state.  Also, outputs the byte sequence
  9.       * to change the state to initial state.
  10.       * This code is assuming the iconv call for initializing the state
  11.       * won't fail due to lack of space in the output buffer.
  12.       */
  13.      #define INIT_SHIFT_STATE(cd, fptr, ileft, tptr, oleft) \
  14.          { \
  15.              fptr = NULL; \
  16.              ileft = 0; \
  17.              tptr = to; \
  18.              oleft = BUFSIZ; \
  19.              (void) iconv(cd, &fptr, &ileft, &tptr, &oleft); \
  20.              (void) fwrite(to, 1, BUFSIZ - oleft, stdout); \
  21.          }

  22.      int
  23.      main(int argc, char **argv)
  24.      {
  25.          iconv_t cd;
  26.          char    from[BUFSIZ], to[BUFSIZ];
  27.          char    *from_code, *to_code;
  28.          char    *tptr;
  29.          const char  *fptr;
  30.          size_t  ileft, oleft, num, ret;

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

  36.          from_code = argv[1];
  37.          to_code = argv[2];

  38.          cd = iconv_open((const char *)to_code, (const char *)from_code);
  39.          if (cd == (iconv_t)-1) {
  40.              /*
  41.               * iconv_open failed
  42.               */
  43.              (void) fprintf(stderr,
  44.                  "iconv_open(%s, %s) failed\\n", to_code, from_code);
  45.              return (1);
  46.          }

  47.          ileft = 0;
  48.          while ((ileft +=
  49.              (num = fread(from + ileft, 1, BUFSIZ - ileft, stdin))) >; 0) {
  50.              if (num == 0) {
  51.                  /*


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

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

  61.                  (void) fprintf(stderr, "Conversion error\\n");
  62.                  return (1);
  63.              }

  64.              fptr = from;
  65.              for (;;) {
  66.                  tptr = to;
  67.                  oleft = BUFSIZ;

  68.                  ret = iconv(cd, &fptr, &ileft, &tptr, &oleft);
  69.                  if (ret != (size_t)-1) {
  70.                      /*
  71.                       * iconv succeeded
  72.                       */

  73.                      /*
  74.                       * Outputs converted characters
  75.                       */
  76.                      (void) fwrite(to, 1, BUFSIZ - oleft, stdout);
  77.                      break;
  78.                  }

  79.                  /*
  80.                   * iconv failed
  81.                   */
  82.                  if (errno == EINVAL) {
  83.                      /*
  84.                     * Incomplete character or shift sequence
  85.                       */

  86.                      /*
  87.                       * Outputs converted characters
  88.                       */
  89.                      (void) fwrite(to, 1, BUFSIZ - oleft, stdout);
  90.                      /*
  91.                       * Copies remaining characters in input buffer
  92.                       * to the top of the input buffer.
  93.                       */
  94.                      (void) memmove(from, fptr, ileft);
  95.                      /*
  96.                       * Tries to fill input buffer from stdin

  97.                       */
  98.                      break;
  99.                  } else if (errno == E2BIG) {
  100.                      /*
  101.                       * Lack of space in output buffer
  102.                       */

  103.                      /*
  104.                       * Outputs converted characters
  105.                       */
  106.                      (void) fwrite(to, 1, BUFSIZ - oleft, stdout);
  107.                      /*
  108.                       * Tries to convert remaining characters in
  109.                       * input buffer with emptied output buffer
  110.                       */
  111.                      continue;
  112.                  } else if (errno == EILSEQ) {
  113.                      /*
  114.                       * Illegal character or shift sequence
  115.                       */

  116.                      /*
  117.                       * Outputs converted characters
  118.                       */
  119.                      (void) fwrite(to, 1, BUFSIZ - oleft, stdout);
  120.                      /*
  121.                       * Initializes the conversion descriptor and
  122.                       * outputs the sequence to change the state to
  123.                       * initial state.
  124.                       */
  125.                      INIT_SHIFT_STATE(cd, fptr, ileft, tptr, oleft);
  126.                      (void) iconv_close(cd);

  127.                      (void) fprintf(stderr,
  128.                       "Illegal character or sequence\\n");
  129.                      return (1);
  130.                  } else if (errno == EBADF) {
  131.                      /*
  132.                       * Invalid conversion descriptor.
  133.                       * Actually, this shouldn't happen here.
  134.                       */
  135.                      (void) fprintf(stderr, "Conversion error\\n");
  136.                      return (1);
  137.                  } else {
  138.                      /*
  139.                       * This errno is not defined
  140.                       */
  141.                      (void) fprintf(stderr, "iconv error\\n");
  142.                      return (1);
  143.                  }
  144.              }
  145.          }


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

  151.          (void) iconv_close(cd);
  152.          return (0);
  153.      }
复制代码





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