在机器人架构中,配置文件是重要组成部分,难用的配置文件系统会阻碍系统开发进度,我们现在来对比几个主流的配置文件格式:TOML、YAML、JSON、INI。这篇文章并非原创,是很多文章的综合,都在参考中一一给出。
我们从以下几个主要的维度来看各种文件格式:
可编辑性。可编辑性是指可以在现有的配置文件上增删内容。
可读性。
C++强类型支持,即配置文件和C++中的类对应。序列化支持主要的容器序。
支持前后兼容性。
配置文件引用功能。配置文件支持引用其他配置文件。
INI INI是出现较早的配置格式,一开始被用在DOS系统上,没有统一语法。它的可读性和可编辑性好。没有C++的强类型支持,不原生支持C++类序列化。不原生支持文件引用。可以视为简单的key-value pair。它是一种伪二维配置格式,维度概念请见附录。总的结论是不推荐使用。有些库支持配置引用。
格式简介 parameter INI所包含的最基本的“元素”就是parameter;每一个parameter都有一个name和一个value,如下所示:
sections 所有的parameters都是以sections为单位结合在一起的。所有的section名称都是独占一行,并且sections名字都被方括号包围着([ and ])。在section声明后的所有parameters都是属于该section。对于一个section没有明显的结束标志符,一个section的开始就是上一个section的结束,或者是end of the file。Sections一般情况下不能被nested,当然特殊情况下也可以实现sections的嵌套。
section如下所示:
在INI文件中注释语句是以分号“;”开始的。所有的所有的注释语句不管多长都是独占一行直到结束的。在分号和行结束符之间的所有内容都是被忽略的。
注释实例如下:
当然,上面讲的都是最经典的INI文件格式,随着使用的需求INI文件的格式也出现了很多变种;
INI实例1:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 ; 通用配置,文件后缀.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文件。有些库支持配置引用。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 { "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,你需要将它包裹在之间—:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 --- 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,你需要将它封装在+++如下之间:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 +++ 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这样的语言来定义配置文件并生成C++代码。
附录 维度概念 这个概念是从一篇帖子 上看到的,根据文件的延展性 , 大致将定义文件分以下几种:
一维 即简单的key-value pair。
1 2 3 4 5 6 7 8 9 10 [key-value] | [key-value] | [key-value] | ... ↑ [y轴]
二维 二维文件可x轴、y轴自由延伸。此类文件的值(value)数据结构从单纯的值变成对象 , 即key-object , 对象当中可以存放值、数组、键等等 , 通过存放键key从而获得x轴延伸能力。
1 2 3 4 5 6 7 8 9 10 11 [ key ] |--[key]--[key]--[key]--[...]--[value] ←x轴 [key-value] | [key-value] | [key-value] | [...] ↑ y轴
伪二维 1 2 3 4 5 6 7 8 [section] ←x轴延伸了一个单位 |---[key-value] |---[key-value] |---[key-value] ... ↑ [y轴]
三维 三维文件则是在二维之上 , 键key的数据机构从单纯的值变成对象 , 从而获得z轴延伸能力。而当键key中可存放键key时 , z轴可无限伸展。
1 2 3 4 5 6 7 8 9 10 11 [ key ] |--[key]--[key]--[key]--[...]--[value] ←x轴 [key-value] \ | [key] [key-value] \ | [key] [key-value] \ | [....] ←z轴 [...] ↑ y轴
伪三维 1 2 3 4 5 6 7 8 9 10 11 [ key ] |--[key]--[key]--[key]--[...]--[value] ←x轴 [key-value] \ | [attribute] ←z轴延伸了一个单位 [key-value] | [key-value] | [...] ↑ y轴
参考