• libxml2中处理中文


    在上篇中简单介绍了libxml2读写XML文件。

    本篇将介绍如何在libxml2中读写中文数据。

    libxml2中提供了编解码器,通过建立自己的编码接口由libxml根据当前编码进行调用,实质上是使用iconv库中的函数实现转换。一般情况下XML使用UTF-8编码,可以实现很好的跨平台性。

    本文将网络上的一段代码复制下来,并应用于系统中,并在32位与64位LINUX平台下测试通过。(源于网络的在64下有问题,我调试了2个多小时才找到问题所在)既然思想来源于网络,在这里也将代码公布在这里。这样就可以直接应用于代码中。

    使用上述代码的方式就是将编码转换初始化,并插入到XML库的接口中。

    就是使用iconv库(LINUX中存在的,libxml也是使用该库),建立utf-8编码与gbk编码的转换接口,并将接口插入到libxml2库中,这样xml库就支持对gb2312和gbk编码的支持了。当然,这个转换不会自动完成,我们需要使用从libxml库中查找特定编码的接口,libxml支持一些基本的编码接口,如:ISO-8859-1,ISO-8859-2等编码,但不支持gbk,所以在上述代码中,我们定义了gbk_input,与gbk_output两个接口,这两个接口是libxml库的标准声明。

    Function type: xmlCharEncodingInputFunc

    Function type: xmlCharEncodingInputFunc
    int	xmlCharEncodingInputFunc	(unsigned char * out, 
    int * outlen,
    const unsigned char * in,
    int * inlen)

    Take a block of chars in the original encoding and try to convert it to an UTF-8 block of chars out.

    out: a pointer to an array of bytes to store the UTF-8 result
    outlen: the length of @out
    in: a pointer to an array of chars in the original encoding
    inlen: the length of @in
    Returns: the number of bytes written, -1 if lack of space, or -2 if the transcoding failed. The value of @inlen after return is the number of octets consumed if the return value is positive, else unpredictiable. The value of @outlen after return is the number of octets consumed.

    还有一个xmlCharEncodingOutputFunc函数,声明与上面是一样的。

    在ConvertInput与ConvertFrom是在libxml库中查找指定编码的接口,并完成编码转换。为了支持GBK,通过xmlNewCharEncodingHandler 来添加新的编码到该编码器中,ConvertXXXX从编码库中找到相应编码的处理器,完成编码与解码工作。

    在实际使用的时候就是使用ConvertXXXX来实现编码与解码。

    如:

    这两个函数返回的是一个字符串指针,内存由ConvertXXX函数分配,需要使用free函数释放。

    在使用完libxml库之后,我们需要释放由iconv_open打开的转换句柄,并且还要释放libxml库的转换资源。

    xmlCleanupCharEncodingHandlers();

    用上述来释放libxml库中的资源。

    后记:

    使用网上的代码,是非常快速的编码方式,当然,我也直接使用了网上的代码,但移植到64位平台时出现了问题,导致浪费了不少的调试时间(使用gdb在代码中查看,使用printf打印指针值,数据....痛苦!)。在上面的代码中,我加入了警示注释,希望自己记住,下次看到这样的代码就知道有问题。

    指针之间的转换编码器是不会告警,所以也没有多注意,那个一整形指针转换成size_t指针类型时,问题在不同平台就会产生问题。size_t定义为平台的数据长度,而int在依然是32位(不保证不变)。

    int a = 10;
    int *pa = &a;
    size_t b;
    size_t *pb;
    pb = pa;
    b = *pb;
    printf("a:%d, b:%zd/n", a, b);
    如上一段简单的代码,在32位平台上输出都是10,64位平台之上输出为a:10, b:-1306831365601230838

    后面那个值是不定的,如果使用-Wall 编码选项,gcc会报一个警告在pb = pa;如果你在32位平台使用pb = (size_t*)pb;那编码器就不会报警,而网上的一份代码就是这样。这也不能责怪源作者,可以环境的不同,考虑自然也就不多了。

    所以,当指针类型转换的时候,一定要注意这个类型,你是否很了解。长度是不是一样的?否则问题出现在平台问题上,是很常难以找到问题所在的。

    版权声明:本文为博主原创文章,未经博主允许不得转载。

  • 相关阅读:
    Log4net中的RollingFileAppender解析
    TortoiseSVN使用简介
    ALinq 入门学习(四)查询关键字
    ALinq 入门学习(五)删除修改数据
    ALinq 入门学习(五)插入数据
    C# 委托知识总结
    sql 分页
    C# 数据结构常用术语总结
    ALinq 入门学习(三)Where 条件查询
    ALinq 入门学习(六)Join 连接查询
  • 原文地址:https://www.cnblogs.com/yin138/p/4902263.html
Copyright © 2020-2023  润新知