次のようなサンプル値を含む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 にあります。
ファイル全体を読み取らないことに関しては、さまざまな方法で実行できます。まず、INI形式のパーサーには少なくともフォワードイテレーターが必要です。したがって、ストリームイテレーターは入力イテレーターであるため使用できません。必要なイテレーターを持つストリーム用に別のクラスを作成できます。 (過去にこのようなクラスをスライディングバッファで作成しました。)メモリマップファイルを使用できます。または、標準ストリームから読み取り、値が見つかるまでパーサーに供給するダイナミックバッファを使用できます。実際のパーサーを使用し、INIファイル構造が正しいかどうかは気にしないでください。ファイル内のトークンを検索するだけです。入力イテレーターで十分です。
最後に、ファイル全体の読み取りを避けることで利点が得られるかどうかはわかりません。 INIファイルは通常非常に小さく、ハードドライブと複数のバッファリングシステムは1バイト以上必要な場合でも1つまたは複数のセクターを読み取るため、パフォーマンスがあるとは思わないファイルを部分的に読み取ろうとする(特に繰り返し行う)ことによる改善。おそらく逆です。
Boostメソッドを使用したINI解析に関するニースの記事を読みました。これは 精神ライブラリを使用したINIファイルリーダー by Silviu Simen です。
簡単です。
ファイルを解析する必要がありますが、これは順番に実行する必要があります。だから、ファイル全体を読んで、すべての値をコレクション(map
またはunordered_map
、おそらく、pair<section, key>
キーとして、またはマップのマップを使用して)必要に応じてそこから取得します。