应用中经常要用到配置文件,ini方式的配置文件以简洁取胜。Windows下也提供了GetPrivateProfileInt、GetPrivateProfileSection、GetPrivateProfileSectionNames、GetPrivateProfileString、GetPrivateProfileStruct和WritePrivateProfileSection、WritePrivateProfileString、WritePrivateProfileStruct等API实现对ini文件的读写功能。但这些API每进行一次读写都需要重新解析一遍文件,不太适合性能敏感场合。并且Windows的ini也并非平台可移植的(平台移植这玩意有时候不考虑不行,考虑的多了也不行)。
Ogre::ConfigFile格式和ini非常像,也是由Section分块的键值对方式,但会在一次性将文件全部解析完并以map<section_name:string, multimap<key:string, value:string>的方式缓存在内存中。这会明显提高多次查询效率。
详读ConfigFile::load源码会发现一些文档中没有描述的细节:
- 默认的键值对分隔符为:"[\t:=]",也可以由用户指定。(不觉得支持的这么多花哨分隔符有啥好处,除了带来混乱)
- 键值对符合格式:"^[ \t\r]*(?<key>.*)[ \t\r]*[\t:=][ \t\r]*(?<value>.*)[ \t\r]*$",可以指定是否忽略空白字符,默认忽略。(ini文件采用的是"^(?<key>.*)=(?<value>.*)$"的方式。这个确实比ini灵活和自然一点,我就有空格控的倾向,习惯在=两边加空格)
- 允许空键,也允许空值
- 行注释符合模式:"^[#@].*$"。(ini文件采用的是"^;.*$"行注释方式。既然仿照ini造轮,为啥又没有兼容ini的方式?)
- Section符合模式:"^\[(?<section_name>.*)]$"
- 同一文件中同一Section可以出现多次,语义叠加
- 一个ConfigFile对象可以对多个cfg文件或者同一个cfg文件多次解析,语义叠加
- 只能以字符串的方式提取值。性能有限,数值格式提取麻烦
- 只读,不能写。也就是说不推荐用程序生成和修改cfg文件
Ogre在这块重新造轮了。毕竟现成成熟的第三方配置解决方案已经很多了:ini、json、xml、yaml、lua、text_format的protobuf也可以算……
参考:
ini与xml之比较
文中对格式的描述采用了.net派的正则表达式,不熟悉的朋友请参考Regular Expression Syntax
2013-3-22
cfg文件只读,这也暗示了该文件格式只可用于配置,而不能作为数据文件,因数据文件可能需要被游戏编辑工具更改。
评论