输入及输出XML和YAML文件


操作

open() 函数: string filename = “I.xml”; FileStorage fs(filename,
FileStorage::WRITE); \… fs.open(filename, FileStorage::READ);
无论以哪种方式绑定,函数中的第二个参数都以常量形式指定你要对文件进行操作的类型,包括:WRITE, READ 或
APPEND。文件扩展名决定了你将采用的输出格式。如果你指定扩展名如 .xml.gz ,输出甚至可以是压缩文件。 当 FileStorage
对象被销毁时,文件将自动关闭。当然你也可以显示调用 release 函数: fs.release();

输入\输出文本和数字

。 数据结构使用与STL相同的 << 输出操作符。输出任何类型的数据结构时,首先都必须指定其标识符,这通过简单级联输出标识符即可实现。基本类型数据输出必须遵循此规则:
fs << “iterationNr” << 100;
读入则通过简单的寻址(通过 [] 操作符)操作和强制转换或 >> 操作符实现:
int itNr;
fs[“iterationNr”] >> itNr;
itNr = (int) fs[“iterationNr”];

输入\输出 vectors(数组)和相应的maps

. 之前提到我们也可以输出maps和序列(数组, vector)。同样,首先输出变量的标识符,接下来必须指定输出的是序列还是map。
对于序列,在第一个元素前输出”[“字符,并在最后一个元素后输出”]“字符:
fs << “strings” << “[”; // 文本 - 字符串序列
fs << “image1.jpg” << “Awesomeness” << “baboon.jpg”;
fs << “]”; // 序列结束
对于maps使用相同的方法,但采用”{“和”}“作为分隔符。
fs << “Mapping”; // 文本 - mapping
fs << “{” << “One” << 1;
fs << “Two” << 2 << “}”;
注意,map为1个string,一个变量交替传入。
对于数据读取,可使用 FileNode 和 FileNodeIterator 数据结构。 FileStorage 的[] 操作符将返回一个 FileNode 数据类型。如果这个节点是序列化的,我们可以使用 FileNodeIterator 来迭代遍历所有元素。
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”]) << "; ";
cout << "One " << (int)(n[“One”]) << endl << endl;

读写自定义数据类型

。 假设你定义了如下数据类型:
class MyData
{
public:
MyData() : A(0), X(0), id() {}
public: // 数据成员
int A;
double X;
string id;
};
添加内部和外部的读写函数,就可以使用OpenCV I/O XML/YAML接口对其进行序列化(就像对OpenCV数据结构进行序列化一样)。内部函数定义如下:
void write(FileStorage& fs) const //对自定义类进行写序列化
{
fs << “{” << “A” << A << “X” << X << “id” << id << “}”;
}

void read(const FileNode& node) //从序列读取自定义类
{
A = (int)node[“A”];
X = (double)node[“X”];
id = (string)node[“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);
}
这儿可以看到,如果读取的节点不存在,我们返回默认值。更复杂一些的解决方案是返回一个对象ID为负值的实例。
一旦添加了这四个函数,就可以用 >> 操作符和 << 操作符分别进行读,写操作:
MyData m(1);
fs << “MyData” << m; // 写自定义数据结构
fs[“MyData”] >> m; // 读自定义数据结构
或试着读取不存在的值:
fs[“NonExisting”] >> m; // 请注意不是 fs << “NonExisting” << m
cout << endl << "NonExisting = " << endl << m << endl;

最终效果:

%YAML:1.0
iterationNr: 100
strings:

  • “image1.jpg”
  • Awesomeness
  • “baboon.jpg”
    Mapping:
    One: 1
    Two: 2
    R: !!opencv-matrix
    rows: 3
    cols: 3
    dt: u
    data: [ 1, 0, 0, 0, 1, 0, 0, 0, 1 ]
    T: !!opencv-matrix
    rows: 3
    cols: 1
    dt: d
    data: [ 0., 0., 0. ]
    MyData:
    A: 97
    X: 3.1415926535897931e+000
    id: mydata1234
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

颢师傅

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值