Как разобрать INI-файл с помощью Boost - PullRequest
60 голосов
/ 30 мая 2011

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

[Section1]
Value1 = 10
Value2 = a_text_string

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

Я искал в этом форуме, чтобы найти несколько примеров (я всегда использовал 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; напротив, я просто хочу читать отдельные значения, когда хочу, и мне не нужно вставлять значения в файл, потому что он уже записан со всеми значениями, которые мне нужны в моей программе.

Ответы [ 4 ]

134 голосов
/ 30 мая 2011

Вы также можете использовать 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;
3 голосов
/ 01 июня 2011

Анализ 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, как правило, довольно малы, и поскольку жесткий диск и несколько систем буферизации в любом случае будут считывать один или несколько секторов (даже если вам нужен только один байт), поэтому я сомневаюсь, что при частичном чтении файла будет какое-либо улучшение производительности (особенноделая это неоднократно), вероятно, наоборот.

2 голосов
/ 22 июня 2011

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

Это простоодин.

1 голос
/ 30 мая 2011

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

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