蓝点工坊(http://www.bluedrum.cn) 创始人,App和嵌入式产品开发。同时也做相应培训和外包工作。 详细介绍 http://pan.baidu.com/s/1y2g88
全部博文(311)
分类: LINUX
2009-11-16 19:30:33
因为指导学员用SDL做歌曲播放及歌词同步功能,以及电子书的阅读,必须牵涉到几种汉字编码的转换.在Windows上可以使用MultiByteToWideChar/WideCharToMultiByte进行转换.在LINUX首先测试了标准C的mbstowbs,测试未果.最后只能集中在使用第三方库 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.5的Utf8,gb2312,gbk和unicode 的字符集名字,分别对应.
UTF8/ UTF-8, GB2312/GBK,UNICODE
而1.13分别对应的名字是
UTF-8,GB2312/GBK,UNICODELITTLE/UNICODEBIG (对应little endian/big endian)
而2.5的转换命令行格式
iconv -f [转换前格式] -t [转换后格式] [源文件] -o [输出文件]
如把GBK的src.txt 转换成UNICODE的dst.txt,可以用如下语句.
iconv -f gbk -t unicode src.txt -o dst.txt
1.13的格式差别较大
iconv -f [转换前格式] -t [转换后格式] [源文件] > [输出文件]
如把GBK的src.txt 转换成UNICODE的dst.txt,而且字符集名字必须用大字.可以用如下语句.
iconv -f GB2312 -t UNICODELITTLE src.txt > dst.txt
而且2.5的转换会把 BOM标志加上.这样更加合理.
以GBK的” 黄新宇
GBK编码是(汉字占两字节,ASCII占一个字节)
0000000 bb c6 d
用1.13版 iconv -f GB2312 -t UNICODELITTLE src.txt > dst.txt转换后的结果
用2.5 版的iconv -f gbk -t unicode src.txt -o dst.txt的转换结果是
0000000 ff fe c4 9e b0 65 87 5b 0d 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之前的值,减去转换后的值.换算出来.
以下是一个gb2313转unicode的代码
/** \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;
}
测试代码
|
(系统内要安装libiconv)
gcc test_text.c -o test_text -liconv
|