LinuxSir.cn,穿越时空的Linuxsir!

 找回密码
 注册
搜索
热搜: shell linux mysql
查看: 1917|回复: 3

linux c 怎么样进行字符编码转换

[复制链接]
发表于 2006-2-10 23:40:08 | 显示全部楼层 |阅读模式
在linux中怎样进行字符编码转换

比如我想把gb2312的字节流转换成utf-8的字节流应该怎么样进行

还有就是编码状态到底是个什么东东 state

希望哪位大哥能小弟指点一下!!!
发表于 2006-2-11 00:17:50 | 显示全部楼层
算你运气好!
应该说gb2312跟utf-8的概念应该不是一个层次上的。gb2312跟unicode都是字符的编码方式,而utf8只是unicode的一种表示方式而已。他们的区别主要在iso8859-1定义的字符集之外(用多字节来表示一个字符)。在linux下有一个iconv库可以完成这些编码之间的转换!
下面的代码是gb2312字节流跟跟utf16字节流之间的转换函数。gb2312跟utf8的转换应该差不多!
两个extern函数为转换入口函数,其它都为内部函数。
  1. /*@author:huangh
  2. *@create time:2005/12/16
  3. */
  4. #include <stdio.h>
  5. #include <iconv.h>
  6. #include <errno.h>
  7. #include <stdlib.h>
  8. #include <string.h>

  9. #define ALIVE() printf("still alive here [%s]:[%d]\n",__FUNCTION__, __LINE__)
  10. /*get the low 8 bits of an unsigned short*/
  11. #define LOWER_SHORT(num) (0x0ff&num)
  12. /*get the high 8 bits of an unsigned short*/
  13. #define HIGH_SHORT(num) ((0xff00&num)>>8)

  14. //#define _BIG_ENDIAN
  15. //#define DEBUG


  16. typedef unsigned int char_16;

  17. static int char16len(char_16 *in_char)
  18. {
  19.     int ret = 0;
  20.     while(in_char[ret])
  21.     {
  22.         ret++;
  23.     }
  24.     return ret;
  25. }
  26. static int gb2312_to_utf16(char *inchar, size_t *in_size, char *outchar, size_t *out_size)
  27. {
  28.     iconv_t cd;
  29.     char **ppinchar = &inchar;
  30.     char **ppoutchar = &outchar;
  31.    
  32.     if ( ( iconv_t )-1 == ( cd = iconv_open( "UCS-2", "GB2312" ) ) )
  33.     {
  34.         perror( "iconv_open() error" );
  35.         return -1;
  36.     }
  37.    
  38.     if ( -1 == iconv( cd, ppinchar, in_size, ppoutchar, out_size ) )
  39.     {
  40.         perror( "iconv() error" );
  41.         goto error;
  42.     }

  43.     {
  44.         int i = 0;
  45.         char *p = outchar;
  46.         while(p[i])
  47.         {
  48.             printf("%2x:", p[i]);
  49.             i++;
  50.         }
  51.     }
  52.     iconv_close(cd);
  53.     return 0;
  54. error:
  55.     iconv_close(cd);
  56.     return -1;
  57. }

  58. static int char_to_char16(char *in, size_t in_size, char_16 out[], size_t out_size)
  59. {
  60.     int i = 0;
  61.     unsigned short high, low;
  62.    
  63.     printf("insize is [%d], out size is [%d]\n", in_size, out_size);   
  64.     if(in_size > 2*out_size)
  65.     {
  66.         return -1;
  67.     }
  68.     ALIVE();
  69.     for(; i<out_size; i++)
  70.     {
  71. #ifdef _BIG_ENDIAN
  72.         high = in[2*i+1]&0xff;
  73.         low  = in[2*i]&0xff;
  74. #else
  75.         high = in[2*i]&0xff;
  76.         low  = in[2*i+1]&0xff;
  77. #endif
  78.         out[i] = (high<<8)|low;
  79.     }
  80.     return 0;
  81. }

  82. static int char16_to_char(char_16 in[], size_t size_in, char *out, size_t size_out)
  83. {
  84.     int i = 0;
  85.     if(size_out < 2*size_in)
  86.     {
  87.         return -1;
  88.     }
  89.     for(; i< size_in; i++)
  90.     {
  91. #ifdef _BIG_ENDIAN
  92.         out[i*2] = LOWER_SHORT(in[i]);
  93.         out[i*2 + 1] = HIGH_SHORT(in[i]);
  94. #else
  95.         out[i*2] = HIGH_SHORT(in[i]);
  96.         out[i*2 + 1] = LOWER_SHORT(in[i]);
  97. #endif
  98.     }
  99.     return 0;
  100. }
  101. static int utf16_to_gb2312(char *inchar, size_t *in_size, char *outchar, size_t *out_size)
  102. {
  103.     iconv_t cd;
  104.     char **ppinchar = &inchar;
  105.     char **ppoutchar = &outchar;
  106.    
  107.     if ( ( iconv_t )-1 == ( cd = iconv_open( "GB2312", "UCS-2") ) )
  108.     {
  109.         perror( "iconv_open() error" );
  110.         return -1;
  111.     }
  112.    
  113.     if ( -1 == iconv( cd, ppinchar, in_size, ppoutchar, out_size ) )
  114.     {
  115.         perror( "iconv() error" );
  116.         goto error;
  117.     }

  118.     iconv_close(cd);
  119.     return 0;
  120. error:
  121.     iconv_close(cd);
  122.     return -1;
  123. }

  124. extern int char_to_utf16(char *in_char, char_16 *out_wchar, size_t out_size)
  125. {
  126.     size_t in_len = strlen(in_char) + 1;
  127.     size_t tmp_len = 2*in_len;
  128.     size_t tmp_len_org;
  129.     char *tmp;
  130.    

  131.     printf("inlen is [%d], out size is [%d]\n", in_len, out_size);   
  132.     if(in_len > 2*out_size)
  133.     {
  134.         return -1;
  135.     }

  136.     if(NULL == (tmp = (char *)malloc(tmp_len)))
  137.     {
  138.         return -1;
  139.     }
  140.     tmp_len_org = tmp_len;

  141.    
  142.     if( 0 != gb2312_to_utf16(in_char, &in_len, tmp, &tmp_len))
  143.     {
  144.         goto error;
  145.     }
  146.     {
  147.         printf("tmp length is [%d]:[%d]\n", tmp_len, in_len);
  148.     }
  149.     if(0 != char_to_char16(tmp, tmp_len_org - tmp_len, out_wchar, out_size))
  150.     {
  151.         goto error;
  152.     }
  153.    
  154.     ALIVE();
  155.     free(tmp);
  156.     return 0;
  157. error:
  158.     free(tmp);
  159.     return -1;
  160. }

  161. extern int utf16_to_char(char_16 *in_char, char *out_char, size_t out_size)
  162. {
  163.     size_t in_size = char16len(in_char) + 1;
  164.     char *tmp;
  165.     size_t in_len ;
  166.     size_t out_len;

  167. #ifdef DEBUG
  168.     int j;
  169.     for(j=0;j<in_size;j++)
  170.     {
  171.         fprintf(stderr, "[%4x]:",in_char[j]);
  172.     }
  173.     fprintf(stderr, "\n");
  174. #endif

  175.     if(NULL == (tmp = (char *)malloc(2*in_size)))
  176.     {
  177.         return -1;
  178.     }
  179.    
  180.     memset(tmp, 0, 2*in_size);

  181.     if(0 != char16_to_char(in_char, in_size, tmp, 2*in_size))
  182.     {
  183.         goto error;
  184.     }
  185. #ifdef DEBUG
  186.     for(j=0; j<2*in_size; j++)
  187.     {
  188.         fprintf(stderr, "[%2x]:",tmp[j]);
  189.     }
  190.     fprintf(stderr, "\n");
  191. #endif
  192.     in_len = in_size*2;
  193.     out_len = out_size;
  194.     if( 0 != (utf16_to_gb2312(tmp, &in_len, out_char, &out_len)))
  195.     {
  196.         goto error;
  197.     }
  198.    
  199.    
  200.     free(tmp);
  201.     return 0;
  202. error:
  203.     free(tmp);
  204.     return -1;
  205. }
复制代码

另外还有一些资料我明天贴上来!
补充一些文档!
1、什么是UTF-8?它与UNICODE是什么关系?
解答:
Unicode的最初目标,是用1个16位的编码来为超过65000个字符提供映射。但这还不够,它不能覆盖全部历史上的文字,也不能解决传输的问题 (implantation head-ache's),尤其在那些基于网络的应用中。已有的软件必须做大量的工作来实现16位的数据。
因此,Unicode用一些基本的保留字符制定了三套编码方式。它们分别是UTF-8,UTF-16和UTF-32。正如名字所示,在UTF-8中,字符是以8位序列来编码的,用一个或几个字节来表示一个字符。这种方式的最大好处,是UTF-8保留了ASCII字符的编码做为它的一部分,例如,在UTF- 8和ASCII中,“A”的编码都是0x41. UTF-16和UTF-32分别是Unicode的16位和32位编码方式。考虑到最初的目的,通常说的Unicode就是指UTF-16。
2、unicode的参考网站
http://www.unicode.org/unicode/standard/principles.html.
3、unicode三种编码之间的转换
http://www.unicode.org/Public/PROGRAMS/CVTUTF/
4、也可以通过查表的方式转换gb2312码和unicode码。表文件见附件gb2312.txt,文件中有使用说明。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x
回复 支持 反对

使用道具 举报

 楼主| 发表于 2006-2-11 02:24:59 | 显示全部楼层
多谢!! 在多发点!!  还能不讲讲编码的字节的表示方式!!
回复 支持 反对

使用道具 举报

发表于 2006-2-11 09:56:26 | 显示全部楼层
  1.    char buff[1024];
  2.    size_t buff_len = 1024;
  3.    size_t s_len = len;
  4.    iconv_t cd = iconv_open("utf-8", "gbk");
  5.    if (cd != iconv_t(-1))
  6.    {
  7.      char* ptr = &buff[0];
  8.      size_t remain = buff_len;
  9.      size_t d_len = iconv(cd, &s, &s_len, &ptr, &remain);
  10.      //for (size_t i=0; i<buff_len-remain; ++i)
  11.      //             cout << buff[i];
  12.      //cout << '\n';
  13.      iconv_close(cd);
  14.    }
复制代码

关于编码的字节的表示,你可以用google搜索一下吗。
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

快速回复 返回顶部 返回列表