C++ 如何使用Boost解析ini文件

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/6175502/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-28 19:37:57  来源:igfitidea点击:

How to parse ini file with Boost

c++parsingboostini

提问by Marcus Barnet

I have a ini file which contains some sample values like:

我有一个 ini 文件,其中包含一些示例值,例如:

[Section1]
Value1 = 10
Value2 = a_text_string

I'm trying to load these values and print them in my application with Boost but I don't understand how to do this in C++.

我正在尝试加载这些值并使用 Boost 在我的应用程序中打印它们,但我不明白如何在 C++ 中执行此操作。

I searched in this forum in order to find some examples (I always used C and so I'm not very good in C++) but I found only examples about how to read values from file all at once.

我在这个论坛中搜索以找到一些示例(我总是使用 C,所以我在 C++ 方面不是很好)但我只找到了关于如何一次从文件中读取值的示例。

I need to load just a single value when I want, like string = Section1.Value2because I don't need to read all the values, but just few of them.

我只需要在需要时加载一个值,就像string = Section1.Value2因为我不需要读取所有值,而只需要读取其中的几个值。

I'd like to load single values and to store them in variable in order to use them when I want in my application.

我想加载单个值并将它们存储在变量中,以便在我的应用程序中使用它们。

It is possible to do this with Boost?

可以用Boost做到这一点吗?

At the moment, I'm using this code:

目前,我正在使用此代码:

#include <iostream>
#include <string>
#include <set>
#include <sstream>
#include <exception>
#include <fstream>
#include <boost/config.hpp>
#include <boost/program_options/detail/config_file.hpp>
#include <boost/program_options/parsers.hpp>

namespace pod = boost::program_options::detail;

int main()
{
   std::ifstream s("file.ini");
    if(!s)
    {
        std::cerr<<"error"<<std::endl;
        return 1;
    }

    std::set<std::string> options;
    options.insert("Test.a");
    options.insert("Test.b");
    options.insert("Test.c");

    for (boost::program_options::detail::config_file_iterator i(s, options), e ; i != e; ++i)
        std::cout << i->value[0] << std::endl;
   }

But this just read all the values in a forloop; at the contrary I just want to read single values when I want and I don't need to insert values in the file, because it is already written with all the values which I need in my program.

但这只是读取for循环中的所有值;相反,我只想在需要时读取单个值,并且不需要在文件中插入值,因为它已经写入了我在程序中需要的所有值。

回答by Timo

You can also use Boost.PropertyTree to read .ini files:

您还可以使用 Boost.PropertyTree 读取 .ini 文件:

#include <boost/property_tree/ptree.hpp>
#include <boost/property_tree/ini_parser.hpp>

...

boost::property_tree::ptree pt;
boost::property_tree::ini_parser::read_ini("config.ini", pt);
std::cout << pt.get<std::string>("Section1.Value1") << std::endl;
std::cout << pt.get<std::string>("Section1.Value2") << std::endl;

回答by Gene Bushuyev

Parsing INI files is easy due to their simple structure. Using AXE I can write in a few lines to parse sections, properties and comments:

由于结构简单,解析 INI 文件很容易。使用 AX 我可以写几行来解​​析部分、属性和注释:

auto trailing_spaces = *space & endl;
auto section = '[' & r_alnumstr() & ']';
auto name = +(r_any() - '=' - endl - space);
auto value = '"' & *("\\"" | r_any() - '"') & '"'
   | *(r_any() - trailing_spaces);
auto property = *space & name & *space & '=' & *space 
    & value & trailing_spaces;
auto comment = ';' & *(r_any() - endl) & endl;
auto ini_file = *comment & *(section & *(prop_line | comment)) & r_end();

More detailed example can be found in the Reference.pdf

更详细的例子可以在Reference.pdf 中找到

Regarding not reading the whole file, it can be done in different ways. First of all, parser for INI format requires at least forward iterators, so you can't use stream iterators, since they are input iterators. You can either create a separate class for stream with required iterators (I wrote one such class in the past with sliding buffer). You can use memory mapped file. Or you can use a dynamic buffer, reading from the standard stream and supplying to parser until you found the values. If you don't want to have a real parser, and don't care if the INI file structure is correct or not, you can simply search for your tokens in the file. Input iterators would suffice for that.

关于不读取整个文件,可以通过不同的方式完成。首先,INI 格式的解析器至少需要前向迭代器,因此您不能使用流迭代器,因为它们是输入迭代器。您可以使用所需的迭代器为流创建一个单独的类(我过去用滑动缓冲区编写了一个这样的类)。您可以使用内存映射文件。或者您可以使用动态缓冲区,从标准流中读取并提供给解析器,直到找到值。如果您不想拥有真正的解析器,并且不关心 INI 文件结构是否正确,您可以简单地在文件中搜索您的令牌。输入迭代器就足够了。

Finally, I'm not sure that avoiding reading the whole file brings any advantages with it. INI files are typically pretty small, and since the hard drive and multiple buffering systems would read one or more sectors anyway (even if you need just one byte), so I doubt there would be any performance improvement by trying to read file partially (especially doing it repeatedly), probably the opposite.

最后,我不确定避免阅读整个文件会带来什么好处。INI 文件通常非常小,而且由于硬盘驱动器和多个缓冲系统无论如何都会读取一个或多个扇区(即使您只需要一个字节),所以我怀疑尝试部分读取文件(尤其是反复这样做),可能恰恰相反。

回答by mosg

I have read a nice article about INI-parsing with boost methods, it's called INI file reader using the spirit libraryby Silviu Simen.

我读过一篇关于使用 boost 方法进行 INI 解析的好文章,它被Silviu Simen称为使用精神库INI 文件阅读器

It's simple one.

这是一个简单的。

回答by Jan Hudec

The file needs to be parsed, which has to be done sequentially. So I'd just read the whole file, store all the values in some collection (mapor unordered_map, probably, either using pair<section, key>as key or using map of maps) and fetch them from there when needed.

文件需要被解析,这必须按顺序完成。所以我只是读取整个文件,将所有值存储在某个集合中(map或者unordered_map,可能使用pair<section, key>作为键或使用地图映射)并在需要时从那里获取它们。