如何用Boost解析ini文件

时间:2021-11-07 22:28:57

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.Value2 because 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 for loop; 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循环中的所有值;相反,我只想在需要的时候读取单个值,而不需要在文件中插入值,因为它已经写入了程序中需要的所有值。

4 个解决方案

#1


125  

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

你也可以使用Boost。读取ini文件的PropertyTree:

#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;

#2


3  

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文件很容易,因为它们的结构很简单。使用AXE,我可以用几行代码来解析部分、属性和注释:

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文件通常非常小,因为硬盘和多个缓冲系统会读取一个或多个部门无论如何(即使你只需要一个字节),所以我怀疑会有任何性能提升试图读文件部分(尤其是反复这样做),可能恰恰相反。

#3


2  

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

我读过一篇关于使用boost方法进行INI解析的文章,这篇文章名为INI file reader,使用Silviu Simen的spirit库。

It's simple one.

这是简单的一个。

#4


1  

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 (map or 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

作为key或map),并在需要时从那里获取它们。
、key>

#1


125  

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

你也可以使用Boost。读取ini文件的PropertyTree:

#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;

#2


3  

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文件很容易,因为它们的结构很简单。使用AXE,我可以用几行代码来解析部分、属性和注释:

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文件通常非常小,因为硬盘和多个缓冲系统会读取一个或多个部门无论如何(即使你只需要一个字节),所以我怀疑会有任何性能提升试图读文件部分(尤其是反复这样做),可能恰恰相反。

#3


2  

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

我读过一篇关于使用boost方法进行INI解析的文章,这篇文章名为INI file reader,使用Silviu Simen的spirit库。

It's simple one.

这是简单的一个。

#4


1  

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 (map or 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

作为key或map),并在需要时从那里获取它们。
、key>