【问题标题】:Read relative file path with Boost Program options使用 Boost Program 选项读取相对文件路径
【发布时间】:2015-03-17 13:14:46
【问题描述】:

我正在开发一个可以从以下位置读取选项的命令行工具:

  • 命令行参数
  • 可选配置文件

我使用Boost Program Options 阅读了这些选项,它几乎可以正常工作。

我的代码是这样的:

namespace po = boost::program_options;
namespace fs = boost::filesystem;

po::variables_map vm;
po::store(po::parse_command_line(argc, argv, options), vm);
po::store(po::parse_config_file(ifs, options, true), vm);
po::notify(vm);

但是,其中一些选项是文件路径,我希望这些选项相对于选项的来源。这是我的意思的一个例子:

假设我的工具位于:/usr/local/bin

mytool --foo.path ../config/assets/toto.txt

解析后,foo.path 选项应该是/usr/local/config/assets/toto.txt 的绝对路径。

现在,如果我在位于/usr/local/config/myconf.cfg 的配置文件中指定foo.path,如下所示:

foo.path=assets/toto.txt

我希望路径相对于配置文件(而不是执行路径),并且生成的绝对路径与以前相同。

在 Boost Program Options 中有没有办法知道选项的值来自哪里,以便在将相对路径转换为绝对路径时调整路径?

【问题讨论】:

    标签: c++ path boost-program-options


    【解决方案1】:

    有一个默认设置为执行路径的工作目录。所有相对路径(您尝试在应用程序中使用)都根据工作目录进行解释。 您必须选择实现目标:

    1. 在解释配置文件中的相对路径之前更改工作目录。如果需要,您应该在完成读取配置后恢复工作目录的默认值。
    2. 一旦你从配置中得到一些路径,你必须检查它是否是相对路径。如果是这样,那么您应该编写代码以使用配置文件的主目录构建正确的路径。

    【讨论】:

    • 这并不能解决问题。相对路径不会神奇地变成绝对路径,因为当前目录已更改。需要知道选项值的来源,才能将相对路径可靠地转换为绝对路径。
    【解决方案2】:

    我终于可以通过在每个解析阶段之后手动添加上下文来让它工作。

    我写的添加上下文的函数如下:

    namespace po = boost::program_options;
    namespace fs = boost::filesystem;
    
    void make_path_absolute(
        const std::string& name,
        po::variables_map& vm,
        const fs::path& root)
    {
        if (vm.count(name) > 0) {
            const auto path = vm[name].as<fs::path>();
    
            if (!path.empty()) {
                vm.at(name).value() = fs::absolute(path, root);
            }
        }
    }
    

    这样使用:

    namespace po = boost::program_options;
    namespace fs = boost::filesystem;
    
    po::variables_map vm;
    
    po::store(po::parse_command_line(argc, argv, options), vm);
    make_path_absolute("foo.path", vm, fs::current_path());
    
    po::store(po::parse_config_file(ifs, options, true), vm);
    make_path_absolute("foo.path", vm, configuration_file.parent_path());
    
    po::notify(vm);
    

    基本上,调用的作用是使路径选项相对于指定的根是绝对的(如果还没有的话)。第一种情况root是执行目录,第二种情况是配置文件的父文件夹。

    【讨论】:

      猜你喜欢
      • 2016-11-12
      • 1970-01-01
      • 2017-03-17
      • 2019-05-16
      • 1970-01-01
      • 2011-06-30
      • 1970-01-01
      相关资源
      最近更新 更多