Как разобрать ini-файл с помощью Boost
у меня есть 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 ответов:
вы также можете использовать 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;
разбор 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();более подробный пример можно найти в файле ссылка.pdf
Что касается не чтения всего файла, это может быть сделано по-разному. Прежде всего, parser для формата INI требует по крайней мере прямых итераторов, поэтому вы не можете использовать потоковые итераторы, поскольку они являются входными итераторами. Вы можете либо создать отдельный класс для потока с требуемыми итераторами (я написал один такой класс в прошлом со скользящим буфером). Вы можете использовать сопоставленный файл памяти. Или вы можете использовать динамический буфер, считывая из стандартного потока и подавая в парсер, пока не найдете значения. Если вы не хотите иметь настоящий парсер, и вам все равно, правильна ли структура файла INI или нет, вы можете просто искать свои токены в файле. Для этого достаточно входных итераторов.
наконец, я не уверен, что избегая чтения всего файла приносит какие-либо преимущества с ним. INI-файлы обычно довольно малы, и поскольку жесткий диск и несколько систем буферизации все равно будут читать один или несколько секторов (даже если вам нужен только один байт), поэтому я сомневаюсь, что будет какое-либо улучшение производительности, пытаясь частично прочитать файл (особенно делать это неоднократно), вероятно, наоборот.
Я прочитал хорошую статью о ini-разборе с помощью методов boost, она называется ini file reader с помощью библиотеки spirit by Сильвиу Симен.
Это просто один.
файл должен быть проанализирован, что должно быть сделано последовательно. Поэтому я просто прочитал весь файл, сохранил все значения в какой-то коллекции (
mapилиunordered_map, вероятно, либо с помощьюpair<section, key>как ключ или с помощью карты карт) и получить их оттуда, когда это необходимо.
Comments