Как разобрать ini-файл с помощью Boost

У меня есть файл ini, который содержит некоторые примеры значений, например:

[Section1]
Value1 = 10
Value2 = a_text_string

Я пытаюсь загрузить эти значения и распечатать их в своем приложении с помощью Boost, но я не понимаю, как это сделать на С++.

Я искал на этом форуме, чтобы найти несколько примеров (я всегда использовал C, поэтому я не очень хорошо разбираюсь в C++), но я нашел только примеры того, как читать значения из файла сразу.

Мне нужно загрузить только одно значение, когда я хочу, например string = Section1.Value2, потому что мне не нужно читать все значения, а только некоторые из них.

Я хотел бы загрузить отдельные значения и сохранить их в переменной, чтобы использовать их, когда захочу, в своем приложении.

Возможно ли это сделать с помощью Boost?

На данный момент я использую этот код:

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

Но это просто чтение всех значений в цикле for; напротив, я просто хочу читать отдельные значения, когда захочу, и мне не нужно вставлять значения в файл, потому что он уже записан со всеми значениями, которые мне нужны в моей программе.


person Marcus Barnet    schedule 30.05.2011    source источник


Ответы (4)


Вы также можете использовать 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;
person Timo    schedule 30.05.2011
comment
что делать, если я не знаю определенного набора доступных ключей, но все же хочу получить полный список пар ключ=значение? т.е. как бы вы переписали свою программу без использования констант Section1.Value1 и Section1.Value2? - person Oleg Vazhnev; 21.04.2013
comment
upd: я нашел этот вопрос stackoverflow.com/questions/11065938/ в соответствии с этим невозможно без написания собственного кода... - person Oleg Vazhnev; 21.04.2013
comment
@javapowered Вопрос, который вы нашли, касается Boost.Program_options, а не Boost.PropertyTree. - person user; 25.02.2014
comment
И здесь это решено: stackoverflow.com/questions/16135285/ - person user; 25.02.2014
comment
Проблема, с которой я всегда сталкивался при работе с Boost.PropertyTree, заключается в использовании , между именами разделов и именами значений. Файлы True INI поддерживают имена разделов и имена значений, которые включают '.' персонаж. Гораздо лучшим разделителем будет / или \. Непечатаемый символ, такой как символ колокольчика (\007), был бы еще лучше. Можно ли настроить это поведение? - person Ben Key; 01.08.2015
comment
Это хорошо, но установка lib-boost-dev огромна в ububut › 50 Mb; Я попытался указать папку boost/property_tree/; но заголовки ссылаются на другие заголовки снаружи; Наконец-то использован simileini.h github.com/brofield/simpleini - person Alex Punnen; 03.05.2017
comment
Вместо ptree я рекомендую использовать iptree без учета регистра. INI-файлы Windows обычно нечувствительны к регистру. - person Muxecoid; 24.06.2020

Разбирать файлы 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();

Более подробный пример можно найти в Reference.pdf.

Что касается не чтения всего файла, то это можно сделать по-разному. Во-первых, синтаксический анализатор для формата INI требует, по крайней мере, прямых итераторов, поэтому вы не можете использовать потоковые итераторы, поскольку они являются итераторами ввода. Вы можете либо создать отдельный класс для потока с необходимыми итераторами (в прошлом я написал один такой класс со скользящим буфером). Вы можете использовать файл отображения памяти. Или вы можете использовать динамический буфер, читая из стандартного потока и предоставляя анализатору, пока не найдете значения. Если вы не хотите иметь настоящий синтаксический анализатор и вам все равно, правильная структура файла INI или нет, вы можете просто искать свои токены в файле. Для этого достаточно итераторов ввода.

Наконец, я не уверен, что избегание чтения всего файла дает какие-либо преимущества. Файлы INI, как правило, довольно малы, и, поскольку жесткий диск и несколько систем буферизации в любом случае будут считывать один или несколько секторов (даже если вам нужен только один байт), поэтому я сомневаюсь, что будет какое-либо улучшение производительности, пытаясь прочитать файл частично (особенно делать это неоднократно), вероятно, наоборот.

person Gene Bushuyev    schedule 01.06.2011
comment
+1 за ссылку на то, что выглядит как полезная библиотека синтаксического анализа для C++11: gbresearch.com/axe< /а> - person Arto Bendiken; 26.09.2014

Файл должен быть проанализирован, что должно быть сделано последовательно. Поэтому я просто читал весь файл, сохранял все значения в какой-то коллекции (map или unordered_map, возможно, либо используя pair<section, key> в качестве ключа, либо используя карту карт) и извлекал их оттуда при необходимости.

person Jan Hudec    schedule 30.05.2011

Я прочитал хорошую статью об анализе INI с помощью методов повышения, она называется читатель файлов INI с использованием Библиотека Spirit, автор Сильвиу Симен.

Это просто.

person mosg    schedule 22.06.2011
comment
он также довольно старый, использующий библиотеку духа «классического» стиля. +1 тем не менее - person sehe; 02.12.2011