输入输出XML和YAML文件
目的
你将得到以下几个问题的答案:
- 如何将文本写入YAML或XML文件,及如何从从OpenCV中读取YAML或XML文件中的文本
- 如何利用YAML或XML文件存取OpenCV数据结构
- 如何利用YAML或XML文件存取自定义数据结构?
- OpenCV中相关数据结构的使用方法,如 :xmlymlpers:FileStorage <filestorage>, FileNode 或 FileNodeIterator.
代码
你可以 点击此处下载 或直接从OpenCV代码库中找到源文件。 samples/cpp/tutorial_code/core/file_input_output/file_input_output.cpp 。
以下用简单的示例代码演示如何逐一实现所有目的.
|
|
代码分析
这里我们仅讨论XML和YAML文件输入。你的输出(和相应的输入)文件可能仅具有其中一个扩展名以及对应的文件结构。XML和YAML的串行化分别采用两种不同的数据结构: mappings (就像STL map) 和 element sequence (比如 STL vector>。二者之间的区别在map中每个元素都有一个唯一的标识名供用户访问;而在sequences中你必须遍历所有的元素才能找到指定元素。
-
XML\YAML 文件的打开和关闭。 在你写入内容到此类文件中前,你必须先打开它,并在结束时关闭它。在OpenCV中标识XML和YAML的数据结构是 FileStorage 。要将此结构和硬盘上的文件绑定时,可使用其构造函数或者 open() 函数:
无论以哪种方式绑定,函数中的第二个参数都以常量形式指定你要对文件进行操作的类型,包括:WRITE, READ 或 APPEND。文件扩展名决定了你将采用的输出格式。如果你指定扩展名如.xml.gz ,输出甚至可以是压缩文件。
当 FileStorage 对象被销毁时,文件将自动关闭。当然你也可以显示调用 release 函数:
-
输入\输出文本和数字。 数据结构使用与STL相同的 << 输出操作符。输出任何类型的数据结构时,首先都必须指定其标识符,这通过简单级联输出标识符即可实现。基本类型数据输出必须遵循此规则:
读入则通过简单的寻址(通过 [] 操作符)操作和强制转换或 >> 操作符实现:
-
输入\输出OpenCV数据结构。 其实和对基本类型的操作方法是相同的:
-
输入\输出 vectors(数组)和相应的maps. 之前提到我们也可以输出maps和序列(数组, vector)。同样,首先输出变量的标识符,接下来必须指定输出的是序列还是map。
对于序列,在第一个元素前输出”[“字符,并在最后一个元素后输出”]“字符:
对于maps使用相同的方法,但采用”{“和”}“作为分隔符。
对于数据读取,可使用 FileNode 和 FileNodeIterator 数据结构。 FileStorage 的[] 操作符将返回一个 FileNode 数据类型。如果这个节点是序列化的,我们可以使用 FileNodeIterator来迭代遍历所有元素。
对于maps类型,可以用 [] 操作符访问指定的元素(或者 >> 操作符):
-
读写自定义数据类型。 假设你定义了如下数据类型:
添加内部和外部的读写函数,就可以使用OpenCV I/O XML/YAML接口对其进行序列化(就像对OpenCV数据结构进行序列化一样)。内部函数定义如下:
接下来在类的外部定义以下函数:
这儿可以看到,如果读取的节点不存在,我们返回默认值。更复杂一些的解决方案是返回一个对象ID为负值的实例。
一旦添加了这四个函数,就可以用 >> 操作符和 << 操作符分别进行读,写操作:
或试着读取不存在的值:
结果
好的,大多情况下我们只输出定义过的成员。在控制台程序的屏幕上,你将看到:
然而, 在输出的xml文件中看到的结果将更加有趣:
或YAML文件: