web-dev-qa-db-fra.com

Comment analyser un fichier ini avec Boost

J'ai un fichier ini qui contient des exemples de valeurs comme:

[Section1]
Value1 = 10
Value2 = a_text_string

J'essaie de charger ces valeurs et de les imprimer dans mon application avec Boost mais je ne comprends pas comment faire cela en C++.

J'ai cherché dans ce forum afin de trouver des exemples (j'ai toujours utilisé C et donc je ne suis pas très bon en C++) mais je n'ai trouvé que des exemples sur la façon de lire les valeurs d'un fichier à la fois.

J'ai besoin de charger une seule valeur quand je veux, comme string = Section1.Value2 parce que je n'ai pas besoin de lire toutes les valeurs, mais seulement quelques-unes.

Je voudrais charger des valeurs uniques et les stocker dans des variables afin de les utiliser quand je le souhaite dans mon application.

Est-il possible de le faire avec Boost?

En ce moment, j'utilise ce 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;
   }

Mais cela ne fait que lire toutes les valeurs dans une boucle for; au contraire, je veux juste lire des valeurs uniques quand je veux et je n'ai pas besoin d'insérer de valeurs dans le fichier, car il est déjà écrit avec toutes les valeurs dont j'ai besoin dans mon programme.

60
Marcus Barnet

Vous pouvez également utiliser Boost.PropertyTree pour lire les fichiers .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;
134
Timo

L'analyse des fichiers INI est facile en raison de leur structure simple. En utilisant AX, je peux écrire en quelques lignes pour analyser les sections, les propriétés et les commentaires:

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();

Un exemple plus détaillé peut être trouvé dans le Reference.pdf

En ce qui concerne la non-lecture de l'intégralité du fichier, cela peut se faire de différentes manières. Tout d'abord, l'analyseur pour INI nécessite au moins des itérateurs de transfert, vous ne pouvez donc pas utiliser d'itérateurs de flux, car ce sont des itérateurs d'entrée. Vous pouvez soit créer une classe distincte pour le flux avec les itérateurs requis (J'ai écrit une telle classe dans le passé avec un tampon coulissant.) Vous pouvez utiliser un fichier mappé en mémoire. Ou vous pouvez utiliser un tampon dynamique, en lisant le flux standard et en fournissant à l'analyseur jusqu'à ce que vous trouviez les valeurs. Si vous ne voulez pas pour avoir un vrai analyseur, et peu importe si la structure du fichier INI est correcte ou non, vous pouvez simplement rechercher vos jetons dans le fichier. Les itérateurs d'entrée suffiraient pour cela.

Enfin, je ne suis pas sûr qu'éviter de lire le fichier entier apporte des avantages. INI sont généralement assez petits, et puisque le disque dur et plusieurs systèmes de mise en mémoire tampon liraient de toute façon un ou plusieurs secteurs (même si vous avez besoin d'un seul octet), je doute donc qu'il y ait des performances amélioration en essayant de lire le fichier partiellement (surtout en le répétant), probablement le contraire.

3
Gene Bushuyev

J'ai lu un article sympa sur l'analyse INI avec les méthodes boost, il s'appelle lecteur de fichiers INI utilisant la bibliothèque des esprits par Silviu Simen .

C'est simple.

2
mosg

Le fichier doit être analysé, ce qui doit être fait de manière séquentielle. Je voudrais donc simplement lire le fichier entier, stocker toutes les valeurs dans une collection (map ou unordered_map, probablement, soit en utilisant pair<section, key> comme clé ou en utilisant une carte de cartes) et les récupérer à partir de là si nécessaire.

1
Jan Hudec