Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1682851
  • 博文数量: 311
  • 博客积分: 7778
  • 博客等级: 少将
  • 技术积分: 4186
  • 用 户 组: 普通用户
  • 注册时间: 2009-11-09 19:59
个人简介

蓝点工坊(http://www.bluedrum.cn) 创始人,App和嵌入式产品开发。同时也做相应培训和外包工作。 详细介绍 http://pan.baidu.com/s/1y2g88

文章存档

2012年(3)

2011年(115)

2010年(170)

2009年(23)

分类: LINUX

2009-11-16 19:30:33

因为指导学员用SDL做歌曲播放及歌词同步功能,以及电子书的阅读,必须牵涉到几种汉字编码的转换.Windows上可以使用MultiByteToWideChar/WideCharToMultiByte进行转换.LINUX首先测试了标准Cmbstowbs,测试未果.最后只能集中在使用第三方库 libiconv来解决编码转换问题了.

 

首先用iconv 编程但是不成功.于是想到先用iconv同名转换工具来测试一把.如果自带工具都不成功,应该还是哪里出问题了.

 

 

Iconv 的版本问题

一测试一下,发现iconv还有一些门道.我的测试环境是 RHEL 5 自带的版本是2.3

gnu 上最新的版本是1.13.

 

iconv --version 各自有如下提示.

 

iconv (GNU libc) 2.5 Copyright (C) 2006 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 由 Ulrich Drepper 编写

 

RHEL 自带的2.3版本

 

 

GNU最新版 1.13

iconv (GNU libiconv 1.13)

Copyright (C) 2000-2009 Free Software Foundation, Inc.

License GPLv3+: GNU GPL version 3 or later <

This is free software: you are free to change and redistribute it.

There is NO WARRANTY, to the extent permitted by law.

作者 Bruno Haible

 

两个工具支持编码集的字符集名字和命令行参数都不一样.这也是为什么从网上找来资料或代码测试不成功的原因.

iconv -l 来显示所支持的字符集.两者名字大不一样.

这里显示的太多,只选几个常用的来作对比.

 

Iconv 2.5Utf8,gb2312,gbkunicode 的字符集名字,分别对应.

UTF8/ UTF-8, GB2312/GBK,UNICODE

1.13分别对应的名字是

 

UTF-8,GB2312/GBK,UNICODELITTLE/UNICODEBIG (对应little endian/big endian)

 

2.5的转换命令行格式

 

iconv -f [转换前格式] -t [转换后格式] [源文件] -o [输出文件]

如把GBKsrc.txt 转换成UNICODEdst.txt,可以用如下语句.

iconv -f gbk -t unicode src.txt -o dst.txt

1.13的格式差别较大

 

iconv -f [转换前格式] -t [转换后格式] [源文件] > [输出文件]

 

如把GBKsrc.txt 转换成UNICODEdst.txt,而且字符集名字必须用大字.可以用如下语句.

iconv -f GB2312 -t UNICODELITTLE src.txt > dst.txt

而且2.5的转换会把 BOM标志加上.这样更加合理.

GBK黄新宇123”编码为例.

 

GBK编码是(汉字占两字节,ASCII占一个字节)

0000000 bb c6 d0 c2 d3 ee 0d 0a 31 32 33

 

  1.13 iconv -f GB2312 -t UNICODELITTLE src.txt > dst.txt转换后的结果

 

   0000000 c4 9e b0 65 87 5b 0d 00 0a 00 31 00 32 00 33 00

2.5 版的iconv -f gbk -t unicode src.txt -o dst.txt的转换结果是

 

  0000000 ff fe c4 9e b0 65 87 5b 0d 00 0a 00 31 00 32 00

0000020 33 00

 这里加上了ff fe 表明是一个UNICODE文件

 


Iconv 编程

 

转换器的操作

typedef void *iconv_t;


extern iconv_t iconv_open (__const char *__tocode, __const char *__fromcode);

extern int iconv_close (iconv_t __cd);

 

iconv的声明

/* Convert at most *INBYTESLEFT bytes from *INBUF according to the

   code conversion algorithm specified by CD and place up to

   *OUTBYTESLEFT bytes in buffer at *OUTBUF. */


extern size_t iconv (iconv_t __cd, char **__restrict __inbuf, size_t *__restrict __inbytesleft,

                     char **__restrict __outbuf, size_t *__restrict __outbytesleft);


 

 

  这里的返回值,转换成功为0,失败为-1.

注意这里__inbytesleft,__outbyteleft,注意两者的含义,都是指针,表示这个函数会改变这个值.iconv执行后,inbytesleft表示输入字符串BUFFER还剩多少字节,如果成功这个值应该为0,__outbytesleft 表示输出BUFFER的还剩多少空间可以用.

   换句话说,如果想知道转换后共占用多少字符.可以用字符__outbytesleft之前的值,减去转换后的值.换算出来.

 

以下是一个gb2313unicode的代码

/** \file
*


*
* \author Andrew Huang
* \date 2009-11-16
*
bluedrum@163.com

*/

int gbk_2_unicode(Uint8 * gbk_buf,int gbk_bytes,Uint8 * uni_buf,int uni_bytes)
{
   Int old_bytes = uni_bytes ;
   iconv_t ih = (iconv_t)-1;
   int len;
   ih = iconv_open("UNICODELITTLE","GB2312");
   if(ih == (iconv_t)-1)
     {
        perror("iconv");
        return -1;
     }    

  len =iconv(ih,(char **)&gbk_buf,(size_t*)&gbk_bytes,(char **)&uni_buf,(size_t*)&uni_bytes);
     iconv_close(ih);
if(len != 0)
   return -1;
else
    return old_bytes-uni_bytes;
}


 

  测试代码



Uint8 gbk_msg[1024] = {0xBB,0xC6,0xD0,0xC2,0xD3,0xEE,0}; //


       Uint16 uni_msg[1024] = {0xE5,0xB5,0x8C,0xE5,0x85,0xA5,0xE5,0xBC,0x8F,0}; 

    int len;

       memset(utf8_msg,0,sizeof(utf8_msg));

  len = gbk_2_unicode(gbk_msg,strlen(gbk_msg),uni_msg,sizeof(uni_msg));


测试方法:

  (系统内要安装libiconv)

gcc test_text.c -o test_text -liconv

文件: test_text.tar.gz
大小: 0KB
下载: 下载

 

阅读(2721) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~