首页 > 代码库 > 利用opencv的FileStorage类实现XML/YAML文件的读写

利用opencv的FileStorage类实现XML/YAML文件的读写

  FileStorage是opencv2.0以后专门用来读写XML/YAML文件的类,标准的C++实现。利用好XML文件可以极大地方便我们对中间数据的处理。

 

官方文档:

(1) http://www.opencv.org.cn/opencvdoc/2.3.2/html/doc/tutorials/core/file_input_output_with_xml_yml/file_input_output_with_xml_yml.html#fileinputoutputxmlyaml

(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 =http://www.mamicode.com/ 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;
}