在机器人架构中,配置文件是重要组成部分,难用的配置文件系统会阻碍系统开发进度,我们现在来对比几个主流的配置文件格式:TOML、YAML、JSON、INI。这篇文章并非原创,是很多文章的综合,都在参考中一一给出。
我们从以下几个主要的维度来看各种文件格式:
- 可编辑性。可编辑性是指可以在现有的配置文件上增删内容。
- 可读性。
- C++强类型支持,即配置文件和C++中的类对应。序列化支持主要的容器序。
- 支持前后兼容性。
- 配置文件引用功能。配置文件支持引用其他配置文件。
INI
INI是出现较早的配置格式,一开始被用在DOS系统上,没有统一语法。它的可读性和可编辑性好。没有C++的强类型支持,不原生支持C++类序列化。不原生支持文件引用。可以视为简单的key-value pair。它是一种伪二维配置格式,维度概念请见附录。总的结论是不推荐使用。有些库支持配置引用。
格式简介
parameter
INI所包含的最基本的“元素”就是parameter;每一个parameter都有一个name和一个value,如下所示:
name = value
sections
所有的parameters都是以sections为单位结合在一起的。所有的section名称都是独占一行,并且sections名字都被方括号包围着([ and ])。在section声明后的所有parameters都是属于该section。对于一个section没有明显的结束标志符,一个section的开始就是上一个section的结束,或者是end of the file。Sections一般情况下不能被nested,当然特殊情况下也可以实现sections的嵌套。
section如下所示:
[section]
comments
在INI文件中注释语句是以分号“;”开始的。所有的所有的注释语句不管多长都是独占一行直到结束的。在分号和行结束符之间的所有内容都是被忽略的。
注释实例如下:
;comments text
当然,上面讲的都是最经典的INI文件格式,随着使用的需求INI文件的格式也出现了很多变种;
INI实例1:
; 通用配置,文件后缀.ini
[common]
application.directory = APPLICATION_PATH "/application"
application.dispatcher.catchException = TRUE
; 数据库配置
resources.database.master.driver = "pdo_mysql"
resources.database.master.hostname = "127.0.0.1"
resources.database.master.port = 3306
resources.database.master.database = "database"
resources.database.master.username = "username"
resources.database.master.password = "password"
resources.database.master.charset = "UTF8"
; 生产环境配置
[product : common]
; 开发环境配置
[develop : common]
resources.database.slave.driver = "pdo_mysql"
resources.database.slave.hostname = "127.0.0.1"
resources.database.slave.port = 3306
resources.database.slave.database = "test"
resources.database.slave.username = "root"
resources.database.slave.password = "123456"
resources.database.slave.charset = "UTF8"
; 测试环境配置
[test : common]
parser和emitter库
JSON
JSON是一个轻量级的数据交换格式,是一种二维的文件格式。不光光可以用来做配置文件,还可以用来传输各种数据。可读性和可编辑性尚可。支持C++强类型,很多C++库支持序列化为json文件。有些库支持配置引用。
{
"firstName": "John",
"lastName": "Smith",
"isAlive": true,
"age": 27,
"address": {
"streetAddress": "21 2nd Street",
"city": "New York",
"state": "NY",
"postalCode": "10021-3100"
},
"phoneNumbers": [
{
"type": "home",
"number": "212 555-1234"
},
{
"type": "office",
"number": "646 555-4567"
}
],
"children": [],
"spouse": null
}
json C++库
YAML
YAML是一种广泛使用的语言,用于跨不同语言和框架的配置文件。专注于简化XML的XML人员名单帮助生成Common XML,这是一个功能强大的XML子集,为XML创建了数据序列化的替代方案,特别是与Python ,Perl和Ruby。它的可读性和可编辑性感觉比json高,支持C++强类型。YAML文件可视为二维。有些库支持配置引用。有些库支持配置引用。
关于YAML语法的简短事实
.yml文件以’ - ‘开头,标记文档的开始
键值对由冒号分隔
列表以连字符开头
YAML使用具有一个或多个空格的缩进来描述嵌套集合
要在前面的问题中使用YAML,你需要将它包裹在之间—:
---
date: '2016-12-14T21:27:05.454Z'
publishdate: '2016-12-14T21:27:05.454Z'
title: Deep dive into TOML, JSON and YAML
tags:
- toml
- yaml
- json
- front matter
type: article
amp:
elements: []
article:
lead: Lorem ipsum.
category: frontmatter
related: []
sitemap:
changefreq: monthly
priority: 0.5
filename: sitemap.xml
---
YAML C++库
TOML
TOML显然是由Tom - Tom Preston-Werner编写的 - 确切地说。这是一个在麻省理工学院授权的开源项目,目前在Github上有超过5k星。2013年3月发布的第一个TOML版本,使TOML成为三个标准的年轻人。TOML文件可视为二维。没有找到C++强类型支持的库,需要自己写。有些库支持配置引用。
TOML的目标是成为最小的配置文件格式,由于精确的语义,这种格式易于阅读。TOML被设计为无歧义地映射到散列表。TOML应该很容易用各种语言来解析数据结构。
关于TOML语法的简短事实
TOML区分大小写。
TOML文件只能包含UTF-8编码的Unicode字符。
空格表示制表符(0x09)或空格(0x20)。
换行符表示LF(0x0A)或CRLF(0x0D0A)。
要在前面的问题中使用TOML,你需要将它封装在+++如下之间:
+++
date = "2016-12-14T21:27:05.454Z"
publishdate = "2016-12-14T21:27:05.454Z"
title = "Deep dive into TOML, JSON and YAML"
tags = ["toml","yaml","json", "front matter"]
type = "article"
[amp]
elements = []
[article]
lead = "Lorem ipsum."
category = "frontmatter"
related = []
[sitemap]
changefreq = "monthly"
priority = 0.5
filename = "sitemap.xml"
+++
toml C++库
总结
综上考虑,个人觉得YAML在各方面都很出众。可读性和可修改性强。此外还有cereal这样的C++库支持,推荐使用。此外,直接使用C++来定义config缺乏扩展性,推荐使用protobuf或者flatbuf这样的DSL语言来定义配置文件并生成C++代码。
附录
维度概念
这个概念是从一篇帖子上看到的,根据文件的延展性 , 大致将定义文件分以下几种:
一维
即简单的key-value pair。
[key-value]
|
[key-value]
|
[key-value]
|
...
↑
[y轴]
二维
二维文件可x轴、y轴自由延伸。此类文件的值(value)数据结构从单纯的值变成对象 , 即key-object , 对象当中可以存放值、数组、键等等 , 通过存放键key从而获得x轴延伸能力。
[ key ]
|--[key]--[key]--[key]--[...]--[value] ←x轴
[key-value]
|
[key-value]
|
[key-value]
|
[...]
↑
y轴
伪二维
[section] ←x轴延伸了一个单位
|---[key-value]
|---[key-value]
|---[key-value]
...
↑
[y轴]
三维
三维文件则是在二维之上 , 键key的数据机构从单纯的值变成对象 , 从而获得z轴延伸能力。而当键key中可存放键key时 , z轴可无限伸展。
[ key ]
|--[key]--[key]--[key]--[...]--[value] ←x轴
[key-value] \
| [key]
[key-value] \
| [key]
[key-value] \
| [....] ←z轴
[...]
↑
y轴
伪三维
[ key ]
|--[key]--[key]--[key]--[...]--[value] ←x轴
[key-value] \
| [attribute] ←z轴延伸了一个单位
[key-value]
|
[key-value]
|
[...]
↑
y轴
参考
作者:不俍
链接:https://zhuanlan.zhihu.com/p/654742516
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。