2007-08-11

iconv库函数的学习程序

关键字: D语言 iconv gb2312 utf-8 utf8
以前用php的iconv函数,使用起来很简单。
用C来写的时候,发现要完全理解了iconv接口才能好程序。
一点不直观。也许是因为性能问题吧,它没有封装一个简单的接口。
对于懒惰的程序员,还是提供一些简单的接口比较好。
因为我们大部分的程序不考虑性能。

我现在不是在写D程序,完全是在写DC程序。
即要考虑C怎么写,又要考虑D怎么用。

附件包括:
学习例程,和libiconv库

编译方法:
文件中有一个make.brf文件, 用 bud @make 编译

需要用到iconv库,请从 http://www.gnu.org/software/libiconv/ 下载
我编译的时候用的是iconv-1.11版本,dmd-1.020 linux系统

/**
 * iconv 转换库的学习程序
 * Edit by Liu Dehong @ 2007/08/11
 *
 * 参考了libiconv接口
 * 本程序的错误处理设计不好,只是个例子。
 * 完全没有处理常见的错误: 非法字符,内存空间
 * 因为有字符串的复制,性能消耗比较大,考虑完全用D语言改写iconv库,
 * 而不是做封装
 *
 */


/**
* 
* 
* 提供跟 GNU libiconv 库的接口
*
* Name:         libiconvD
* Purpose:      方便在D语言里实现国际编码之间的转换
*
* Author:       张雪平(heromyth)
* Email:        zxpmyth@yahoo.com.cn
* Date:         2007-6-14
* Version:      1.0.1
* Copyrights:   (c) Public Domain and BitWorld Inc.
* Licence:      BSD licence
* 
* Plan:         实现方便在D语言里直接使用的函数或者类
* 
**/

module libiconvD;

alias libiconv iconv ;  ///
alias libiconv_open iconv_open ;  ///
alias libiconv_close iconv_close ; ///


typedef void* iconv_t;

/**
* 设置要转换的编码,并为转换操作准备空间
* 
* Params:
*   fromcode = 需要被转换的源数据的编码格式
*   tocode   = 需要转换成的目标数据的编码格式
* 
* Returns:
*   (iconv_t)(-1),如果设置有错误;<br>
*   新分配的转换描述信息器,如果设置成功。
* 
* See_Also:
*   iconv_open.3.html
* 
* 注意:
*   参数的顺序一下不能错,否则会造成后面的转换失败
*   所有支持编码可以在参考里找到
*
*/
extern (C) iconv_t libiconv_open (char *tocode, char *fromcode);


/**
* 转换核心函数
* 
* Params:
*   cd             = 转换描述信息器,由libiconv_open提供,可存放转换过程状态
*   inbuf          = 指向源字符序列的第一个位置;在执行后,指向新的空间地址:*inbuf + *inbytesleft
*   inbytesleft    = 源字符序列的字节数;在执行后,通常为0,否则为剩余未被转换的字符数
*   outbuf         = 指向存放目标字符序列的首地址;在执行后,指向新的空间地址:*outbuf + 实际转换的字节数
*   outbytesleft   = 存放目标字符序列的总的空间字节数;剩余的目标空间字节数
* 
* Returns:
*   (iconv_t)(-1) 如果转换有问题;<br>
*   0,调用过程中没有使用可逆转换;<br>
*   其它正数,在一次调用过程中以非可逆方式进行转换的字符数
* 
* 注意:
*   对各个参数含义的理解一定要正确,否则很难正确使用这个函数
*
*/
extern (C) size_t libiconv (iconv_t cd, char* * inbuf, size_t *inbytesleft, char* * outbuf, size_t *outbytesleft);


/**
* 释放先前申请的准备空间
* 
* Params:
*   cd = 指向先前由libiconv_open申请的转换描述信息器空间
*
*/
extern (C) int libiconv_close (iconv_t cd);

import std.stdio;
import std.c.string;
import std.string;
import std.c.stdlib;

char[] utf8_to_gb2312(char[] str)
{
    return code_conver("utf-8", "gb2312", str);
}

char[] gb2312_to_utf8(char[] str)
{
    return code_conver("gb2312", "utf-8", str);
}

char[] code_conver(string from, string to, in char[] in_str)
{
    auto cd = iconv_open(toStringz(to), toStringz(from));
    if (cd == cast(iconv_t)-1)
    {
        throw new Error("Can't Open from " ~ from ~ " to " ~ to);
        writefln("aaaa");
    }

	uint in_len = in_str.length;
	auto inp = toStringz(in_str);

	uint out_len = 2 * in_len;   // may be enough
	char* outp = cast(char*) malloc(out_len * char.sizeof);
    auto old_outp = outp;

    debug (1) {
    writefln("in_str.ptr: %s", in_str.ptr);
    writefln("inp: %s", inp);
    writefln("oup: %s", outp);
    }

    auto old_in_len = in_len;
    auto old_out_len = out_len;
    auto i = iconv(cd, &inp, &in_len, &outp, &out_len);
    auto conv_len = old_out_len - out_len;

	iconv_close(cd);

    debug (1) {
    writefln("i: %s", i);
    writefln("inp: %s", inp);
    writefln("oup: %s", outp);
    writefln("in_len: %s", in_len);
    writefln("out_len %s", out_len);
    }

    debug (1) {
    //printf("%s", inp);
    printf("inp: %s"\n, inp - old_in_len);
    printf("outp: %s"\n, outp - conv_len);
    }

    auto ret = toString(old_outp).dup;
    free(old_outp);

    return ret;
}

void main()
{

    try
    {
        auto str1 = utf8_to_gb2312("aabb我bb");
        printf("return: %.*s"\n, str1);

        auto str2 = gb2312_to_utf8(str1);
        printf("return: %.*s"\n, str2);
    }
    catch (Error err)
    {
        writefln("catch error: %s", err);
    }

    return ;
}

  • d_iconv.zip (515.1 KB)
  • 描述: 学习例程,和libiconv库
  • 下载次数: 15
评论
发表评论

您还没有登录,请登录后发表评论

sofire
搜索本博客
最近加入圈子
存档
最新评论
评论排行榜