Nice programing

Boost로 ini 파일을 구문 분석하는 방법

nicepro 2020. 12. 3. 19:41
반응형

Boost로 ini 파일을 구문 분석하는 방법


다음과 같은 샘플 값이 포함 된 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루프의 모든 값을 읽습니다 . 반대로 저는 원할 때 단일 값을 읽고 싶고 파일에 값을 삽입 할 필요가 없습니다. 이미 프로그램에서 필요한 모든 값으로 작성 되었기 때문입니다.


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 파일은 구조가 단순하여 파싱이 쉽습니다. 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 에서 찾을 수 있습니다.

Regarding not reading the whole file, it can be done in different ways. First of all, parser for INI format requires at least forward iterators, so you can't use stream iterators, since they are input iterators. You can either create a separate class for stream with required iterators (I wrote one such class in the past with sliding buffer). You can use memory mapped file. Or you can use a dynamic buffer, reading from the standard stream and supplying to parser until you found the values. If you don't want to have a real parser, and don't care if the INI file structure is correct or not, you can simply search for your tokens in the file. Input iterators would suffice for that.

Finally, I'm not sure that avoiding reading the whole file brings any advantages with it. INI files are typically pretty small, and since the hard drive and multiple buffering systems would read one or more sectors anyway (even if you need just one byte), so I doubt there would be any performance improvement by trying to read file partially (especially doing it repeatedly), probably the opposite.


I have read a nice article about INI-parsing with boost methods, it's called INI file reader using the spirit library by Silviu Simen.

It's simple one.


The file needs to be parsed, which has to be done sequentially. So I'd just read the whole file, store all the values in some collection (map or unordered_map, probably, either using pair<section, key> as key or using map of maps) and fetch them from there when needed.

참고URL : https://stackoverflow.com/questions/6175502/how-to-parse-ini-file-with-boost

반응형