OPENCV XML函数完美支持中文方法

减小字体 增大字体作者:沈乐君  来源:本站原创  发布时间:2009-05-27 18:50:03

XML即extensibe markup language的缩写,也就是可扩展标识语言。由于其开放性,越来越多的软件采用它作为描述语言;由于其平台无关性,越来越多的系统采用它作为数据传递中介。计算机行业已经把XML为数据交换的标准,并提供了相当数量的支持工具。但是,C++中解析xml还依然不够完美,特别是对于中文字符集的支持。大家总是遇到各种问题,本文改进了OPENCV的XML读写函数,支持中文字符串。

在OPENCV开发包中,存在着读写XML的一系列函数,虽然并不完善,有些功能还有欠缺。但是,比起动辄几兆的XML读写开发包(如Xerces-C++),它容易使用,代码量小。对于在计算机视觉研究过程中的数据交换任务,这些简单IO函数基本足够了。唯一可惜的是,它目前不支持中文,在某些需要中文字符串的场合,有些遗憾。能不能通过简单的修改,让它支持中文?作者做了如下试验,修改方法简单可行!

首先,分析cxpersistence.cpp中的函数,发现只需要修改一处就能够让XML系列函数支持中文[2]。也就是检测字符C是否可打印的宏cv_isprint。即将:
#define cv_isprint(c)     ((signed char)(c) >= (signed char)' ')
替换为
#define cv_isprint(c)     ((unsigned char)(c) >= 0x20 )

经过一系列测试,发现这样的修改是可行的。在debug版完全正常,可是,当用release发布时。VC罢工了,编译的程序进入类似死循环的状态。接着,进入漫长的release版本和debug版本的剖析分析[3]。

最终,得到结论:DEBUG版和RELEASE版的区别,是cxpersistence.cpp中的XML解析函数用到的isdigit(),isalpha(),isalnum(),isspace()等C库函数,其DEBUG版和RELEASE版的行为居然不一样。解决这些问题的途径很多,最简单的方法就是,将cxpersistence.cpp中所有的
char c
替换为
unsigned char c

通过上述2处修改,OPENCV的XML读写函数,完全支持中文(包括简体和繁体)了。呵呵!

测试程序如下

int sub_test_opencv_xml_write(void)
{
	// 创建文件存储对象
	CvFileStorage *fs=cvOpenFileStorage("test.xml",0,CV_STORAGE_WRITE);
	// 写注释
	cvWriteComment(fs,"测试写XML文件",1);
	
	// 开始写结构,类型是图map,也就是有名字的无序节点集合
	cvStartWriteStruct(fs,"Employee",CV_NODE_MAP);
	// 注释
	cvWriteComment(fs,"MAP类型,姓名,年龄,薪水",1);
	// 姓名
	cvWriteString(fs,"name","刘越");
	// 年龄
	cvWriteInt(fs,"age",18);
	// 薪水
	cvWriteReal(fs,"salary",2780.3);
	// 销售次数
	cvWriteInt(fs,"sales_count",4);
	{
		// 销售具体数据
		int sales_record[]={30000,4200,50090};
		// 注释
		cvWriteComment(fs,"SEQ类型,销售记录",1);
		// 开始写结构,类型是序列sequence,无名字的有序节点集合
		cvStartWriteStruct(fs,"sales_record",CV_NODE_SEQ);
		// 前3条销售记录
		cvWriteRawData(fs,sales_record,3,"i");
		// 第4条销售记录,注意无名字
		cvWriteInt(fs,0,6100);
		// 结束
		cvEndWriteStruct(fs);
	}
	{
		// 注释
		cvWriteComment(fs,"MAP类型,亲友",1);
		// 开始
		cvStartWriteStruct(fs,"Parent",CV_NODE_MAP);
		// 父亲
		cvWriteString(fs,"father","杨舜");
		// 母亲
		cvWriteString(fs,"mother","王娟");
		// 结束
		cvEndWriteStruct(fs);
	}
	// 结束
	cvEndWriteStruct(fs);
	// 释放文件存储对象
	cvReleaseFileStorage(&fs);
}

int sub_test_opencv_xml_read(void)
{
	// 文件节点
	CvFileNode * node, *node2;
	char * str;
	int count;
	int * d;
	
	//cve_dm.debug_break();
	// 打开XML文件
	CvFileStorage *fs = cvOpenFileStorage("test.xml",0,CV_STORAGE_READ);
	// 获得第一层数据节点
	node = cvGetFileNodeByName(fs,0,"Employee");
	str = cvReadStringByName(fs,node,"name");
	printf("\n姓名=%s",str);
	printf("\n年龄=%d",cvReadIntByName(fs,node,"age"));
	printf("\n薪水=%g",cvReadRealByName(fs,node,"salary"));
	count = cvReadIntByName(fs,node,"sales_count");
	printf("\n销售%d条",count);
	d = cvAlloc(sizeof(int)*count);
	if(d)
	{
		int i;
		node2 = cvGetFileNodeByName(fs,node,"sales_record");
		if(node2)
		{
			cvReadRawData(fs,node2,d,"i");
			printf("\n销售记录=");
			for(i=0;i<count;i++)
				printf("%d, ",d[i]);
		}
		cvFree(&d);
	}
	// 获得第二层节点
	node = cvGetFileNodeByName(fs,node,"Parent");
	printf("\n根节点=%s",cvGetFileNodeName(node));
	str = cvReadStringByName(fs,node,"father");
	printf("\n父亲=%s",str);
	str = cvReadStringByName(fs,node,"mother");
	printf("\n母亲=%s",str);
}

开发环境: VC6.0 + WINXP。

若您有任何改进建议,请告诉我 ^_^

参考文献:
[1]邹月明, 剖析Xml4C源码,完美兼容中文XML
[2]ASCII 、GB2312、GBK、GB18030、unicode、UTF-8字符集编码详解
[3]Joseph M. Newcomer, Surviving the Release Version
 

opencv xml,xml解析,xml c++,xml读写

  • 好的评价 如果您觉得此文章好,就请您
      100%(3)
  • 差的评价 如果您觉得此文章差,就请您
      0%(0)
   评论摘要(共 0 条,得分 0 分,平均 0 分) 查看完整评论

用户名:   验证码:

分 值:100分 85分 70分 55分 40分 25分 10分 1分

内 容:

      若文章有错误,请将右边打钩通知管理员

关于本站 - 友情连接 - 网站地图 - 我要留言