FileStorage是opencv2.0以后专门用来读写XML/YAML文件的类,标准的C++实现。利用好XML文件可以极大地方便我们对中间数据的处理。
官方文档:
(2) http://docs.opencv.org/modules/core/doc/xml_yaml_persistence.html#filestorage
利用FileStorage主要可以完成对以下几种数据的的输入和输出:数字、文本(字符串)、数组(vector)、maps、自定义数据类型(类)。与C++标准输入输出流的操作方法基本一致:
建立流对象-->打开文件(建立流与文件的连接)-->进行读或写操作-->关闭文件(断开流与文件的连接)。
使用过程中需要注意以下几点:
(1)打开文件的时候要指定是"WRITE"还是"READ",一旦指定就只能读或写。写完了要读或者读完了要写前,要先对流对象进行重定向(可以使用FileStorage::open()方法);
(2)读写可以使用重载的<<和>>操作符,与C++风格保持了一致;
(3)FileStorage的[]操作符返回一个FileNode数据类型,如果该节点是序列化的(vector),可以使用FileNodeIterator来迭代遍历该节点所有元素;
(4)每次将FileStorage对象重定向到"WRITE"后,都会从头开始写,即会覆盖之前的全部内容;
(5)读写自定义的数据类型(自定义类)时,要分别添加内部和外部的读写函数,外部的读写函数相当于对FileStorage对象的插入“<<”和提取“>>”运算符的重载,它们又调用了自定义类的内部读写函数,完成对数据成员的读写。
以下是我的实验代码:
#include <opencv2/core/core.hpp>
#include <iostream>
#include <string>using namespace std;
using namespace cv;class MyData //用户自定义类
{
public:
MyData() : A(0), X(0), id() {}
MyData(int i) : X(0), id()
{
A = i;
}
public:
int A;
double X;
string id;
public:
//添加内部读写函数
void write(FileStorage& fs) const
{
fs << "{" ;
fs << "A" << A ;
fs << "X" << X ;
fs << "id" << id;
fs << "}";
}
void read(const FileNode& node)
{
A = (int)(node["A"]);
X = (double)(node["X"]);
id = (string)(node["id"]);
/*node["A"] >> A;
node["X"] >> X;
node["id"] >> id;*/
}
};//添加外部读写函数
void write(FileStorage& fs, const std::string&, const MyData& x)
{
x.write(fs);
}
void read(const FileNode& node, MyData& x, const MyData& default_value = MyData())
{
if(node.empty())
x = default_value;
else
x.read(node);
}
//重载<<操作符用于向标准输出流输出自定义类
static ostream& operator<<(ostream& out, const MyData& m)
{
out << "{ id = " << m.id << ", ";
out << "X = " << m.X << ", ";
out << "A = " << m.A << "}";
return out;
}int main(int argc, char* argv[])
{
//打开XML文件
string filename = "I.xml";
//------------(1)------------
FileStorage fs(filename, FileStorage::WRITE);
//------------(2)------------
//fs.open(filename, FileStorage::READ);//----------------简单数据结构输入输出----------------
//输出数字和文本
fs << "iterationNr" << 100;
//输入数字和文本
//fs.open(filename, FileStorage::READ); //不要忘记将fs重定向为"READ"
//int itNr;
//------------(1)------------
//fs["iterationNr"] >> itNr;
//------------(2)------------
//itNr = (int)fs["iterationNr"];
//cout<<"iterationNr "<<itNr;//输出大型数据结构Mat
Mat R = Mat_<uchar >::eye (3, 3),
T = Mat_<double>::zeros(3, 1);
fs << "R" << R;
fs << "T" << T;
//输入Mat
//fs.open(filename, FileStorage::READ); //不要忘记将fs重定向为"READ"
//fs["R"] >> R;
//fs["T"] >> T;
//----------------------------------------------------------//----------------复杂数据结构输入输出----------------
//输出数组(vector)
fs<<"strings";
fs<<"[";
fs<<"image1.jpg"<<"Awesomeness"<<"baboon.jpg";
fs<<"]";
//输出maps
fs<<"Mapping";
fs<<"{";
fs<<"One"<<1;
fs<<"Two"<<2;
fs<<"}";//输入数组
//fs.open(filename, FileStorage::READ); //不要忘记将fs重定向为"READ"
//FileNode n = fs["strings"]; // 读取字符串序列 - 获取节点
//if (n.type() != FileNode::SEQ)
//{
// cerr << "strings is not a sequence! FAIL" << endl;
// return 1;
//}
//FileNodeIterator it = n.begin(), it_end = n.end(); // 遍历节点
//for (; it != it_end; ++it)
// cout << (string)*it << endl;
////输入maps
//n = fs["Mapping"]; // 从序列中读取map
//cout << "Two " << (int)(n["Two"]) << endl;
//cout << "One " << (int)(n["One"]) << endl;
//----------------------------------------------------------//----------------自定义类输入输出----------------
MyData m(1);
//向文件输出
fs << "MyData" << m;
//由文件输入
fs.open(filename, FileStorage::READ); //不要忘记将fs重定向为"READ"
fs["MyData"] >> m;
fs["NonExisting"] >> m; // 请注意不是 fs << "NonExisting" << m
cout << endl << "NonExisting = " << endl << m << endl;
//----------------------------------------------------------//关闭XML文件
fs.release();return 0;
}
利用opencv的FileStorage类实现XML/YAML文件的读写