您的位置:首页 > 运维架构

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

2010-04-13 19:30 260 查看
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]。本文来自:http: //www.shenlejun.cn.

最终,得到结论: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。

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

转自http://www.shenlejun.cn/my/article/show.asp?id=35,没试过里面的方法,只是想拿来分享下,有用的时候再来看看。

参考文献:
[1]邹月明, 剖析Xml4C源码,完美兼容中文XML
[2]ASCII 、GB2312、GBK、GB18030、unicode、UTF-8字符集编码详解
[3]Joseph M. Newcomer, Surviving the Release Version
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: