输入输出XML和YAML文件(1):
XML和YAML文件简介;FileStorage类操作文件的使用引导;
一,XML和YAML文件简介
XML,即eXtensible Markup Language,翻译成中文为“可扩展标识语言”。首先,XML是一种元标记语言。所谓“元标记”,就是开发者可以根据自身需要定义自己的标记,比如可以定义标记<book>、<name>。任何满足XML命名规则的名称都可以标记,这就向不同的应用程序打开了的大门。此外,XML是一种语义/结构化语言,它描述了文档的结构和语义。
YAML是“YAML Ain't a Markup Language”(译为“YAML不是一种置标语言”)的递回缩写。在开发的这种语言时,YAML的原意是:“Yet Another MarkupLanguage”(仍是一种置标语言),但为了强调这种语言以数据为中心,而不是以置标语言为重点,而用返璞词进行重新命名。YAML是一个可读性高,用来表达资料序列的格式。它参考了其他多种语言,包括:XML、C语言、Python、Perl,以及电子邮件格式RFC2822。
总之,YAML试图用一种比XML更敏捷的方式,来完成XML所完成的任务。
二,FileStorage类操作文件的使用引导
XML和 YAML是使用非常广泛的文件格式,可以利用XML或者YAML格式的文件存储和还原各式各样的数据结构。当然,它们还可以存储和载入任意复杂的数据结构,其中就包括了OpenCV相关周边的数据结构,以及各种原始数据类型,如整数和浮点数字和文本字符串。
我们一般使用如下过程来写入或者读取数据到XML或YAML文件中。
(1)实例化一个 FileStorage类的对象,用默认带参数的构造函数完成初始化,或者用FileStorage::open()成员函数辅助初始化。
(2)使用流操作符<<进行文件写入操作,或者>>进行文件读取操作,类似C++中的文件输入输出流。
(3)使用FileStorage::release()函数析构掉FileStorage类对象,同时关闭文件。
下面分别对这三个步骤进行实例讲解。
1.【第一步】XML、YAML文件的打开
(1)准备文件写操作
FileStorage是 OpenCV 中XML和YAML文件的存储类,封装了所有相关的信息。它是OpenCV从文件中读数据或向文件中写数据时必须要使用的一个类。
此类的构造函数为FileStorage:FileStorage,有两个重载,如下。
C++: Filestorage : :Filestorage ()
C++: FileStorage::FileStorage (const string& source,int flags,conststring& encoding=string ())
构造函数在实际使用中,方法一般有两种。
1)对于第二种带参数的构造函数,进行写操作范例如下。Filestorage fs ("abc.xml",Filestorage : : wRITE);
2)对于第一种不带参数的构造函数,可以使用其成员函数FileStorage::open进行数据的写操作,范例如下。
Filestorage fs;
fs.open ( "abc.xml",Filestorage: : WRITE);(2)准备文件读操作
上面讲到的都是以FileStorage:: WRITE为标识符的写操作,而读操作,采用FileStorage::READ标识符即可,相关示例代码如下。
1)第一种方式
Filestorage fs ("abc.xml",Filestorage : : READ);
2)第二种方式
Filestorage fs;
fs.open("abc. xml",Filestorage: : READ);
另外需要注意的是,上面的这些操作示例是对XML文件为例子作演示的,而对YAML文件,操作方法是类似的,就是将XML文件换为YAML文件即可。
2.【第二步】进行文件读写操作
(1)文本和数字的输入和输出
定义好FileStorage类对象之后,写入文件可以使用“<<”运算符,例如:
fs <<"iterationNr" << 100;
而读取文件,使用“>>”运算符,例如:
int itNr;
fs [ "iterationNr"] >> itNr;
itNr = (int) fs ["iterationNr" ];
(2) OpenCV数据结构的输入和输出
关于OpenCV 数据结构的输入和输出,和基本的C++形式相同,范例如下。
//数据结构的初始化
Mat R = Mat_<uchar > : :eye (3,3) ,
Mat T = Mat_<double> : : zeros (3,1);//向Mat中写入数据
fs <<"R"<<R;
fs <<"T"<< T;
//从Mat中读取数据
fs [ "R" ] >> R;
fs["T"]>>T;
3.【第三步】vector (arrays)和 maps的输入和输出
对于vector 结构的输入和输出,要注意在第一个元素前加上“[”,在最后一个元素前加上“]”。例如:
fs <<"strings" <<"[ "; //开始读入string文本序列
fs << "imagel.jpg"<<"Awesomeness" <<"baboon.jpg";
fs <<"]";//关闭序列
而对于map 结构的操作,使用的符号是“{”和“}”,例如:
fs <<"Mapping" ;// 开始读入Mapping文本
fs << "{ ”<<"one" << 1;
fs <<"Two" <<2 <<"} ";
读取这些结构的时候,会用到 FileNode和 FileNodelterator数据结构。对FileStorage类的“[”、“]”操作符会返回FileNode数据类型;对于一连串的node,可以使用FileNodeIterator 结构,例如:
FileNode n = fs [ "strings" ] ;//读取字符串序列以得到节点
if (n.type() != FileNode : : SEQ)
{
cerr <<"发生错误!字符串不是一个序列!" <<endl;return l;
}
FileNodeIterator it = n.begin (), it_end = n.end();//遍历节点
for (; it != it_end; ++it)
cout<<(string) *it <<endl;
4.【第四步】文件关闭
需要注意的是,文件关闭操作会在 FileStorage类销毁时自动进行,但我们也
可显式调用其析构函数FileStorage::release()实现。FileStorage:.release()函数会析构掉FileStorage类对象,同时关闭文件。
调用过程非常简单,如下。
fs.release ( );