c++ parsing boost ini

c++ - Cómo analizar el archivo ini con Boost



parsing (4)

Tengo un archivo ini que contiene algunos valores de muestra como:

[Section1] Value1 = 10 Value2 = a_text_string

Estoy intentando cargar estos valores e imprimirlos en mi aplicación con Boost, pero no entiendo cómo hacerlo en C ++.

Busqué en este foro para encontrar algunos ejemplos (siempre usé C y, por lo tanto, no soy muy bueno en C ++), pero solo encontré ejemplos sobre cómo leer valores de un archivo al mismo tiempo.

Necesito cargar solo un valor cuando lo desee, como string = Section1.Value2 porque no necesito leer todos los valores, pero solo algunos de ellos.

Me gustaría cargar valores únicos y almacenarlos en variables para usarlos cuando quiera en mi aplicación.

¿Es posible hacer esto con Boost?

Por el momento, estoy usando este código:

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

Pero esto acaba de leer todos los valores en un ciclo for ; por el contrario, solo quiero leer valores individuales cuando quiero y no necesito insertar valores en el archivo, porque ya está escrito con todos los valores que necesito en mi programa.


Analizar archivos INI es fácil debido a su estructura simple. Usando AX puedo escribir en algunas líneas para analizar secciones, propiedades y comentarios:

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

Se puede encontrar un ejemplo más detallado en Reference.pdf

En cuanto a no leer todo el archivo, se puede hacer de diferentes maneras. En primer lugar, el analizador para el formato INI requiere al menos iteradores hacia adelante, por lo que no puede usar iteradores de flujo, ya que son iteradores de entrada. Puede crear una clase separada para el flujo con los iteradores requeridos (escribí una de esas clases en el pasado con el buffer deslizante). Puede usar un archivo mapeado de memoria. O puede usar un búfer dinámico, leyendo de la secuencia estándar y suministrando al analizador hasta que encuentre los valores. Si no desea tener un analizador real, y no le importa si la estructura del archivo INI es correcta o no, simplemente puede buscar sus tokens en el archivo. Los iteradores de entrada serían suficientes para eso.

Finalmente, no estoy seguro de que evitar leer todo el archivo tenga alguna ventaja. Los archivos INI suelen ser bastante pequeños, y dado que el disco duro y los múltiples sistemas de almacenamiento en búfer leerían uno o más sectores de todos modos (incluso si necesita solo un byte), dudo que haya una mejora en el rendimiento al intentar leer archivos parcialmente (especialmente haciéndolo repetidamente), probablemente lo contrario.


El archivo debe ser analizado, lo que debe hacerse de forma secuencial. Así que acabo de leer todo el archivo, almacenar todos los valores en alguna colección ( map o unordered_map , probablemente, ya sea usando pair<section, key> como clave o usando un mapa de mapas) y buscarlos desde allí cuando sea necesario.



También puede usar Boost.PropertyTree para leer archivos .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;