You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用boost::property_tree解析XML中带单位的std::chrono::duration字段?

如何用Boost.PropertyTree解析带单位的字符串到std::chrono::nanoseconds?

问题描述

我希望配置文件写成如下形式:

<?xml version="1.0" encoding="UTF-8"?>
<Config>  
  <DurationValue>20ns</DurationValue>
</Config>

或者:

<?xml version="1.0" encoding="UTF-8"?>
<Config>  
  <DurationValue>15s</DurationValue>
</Config>

需要统一解析DurationValue字段,最终存储为std::chrono::nanoseconds类型。我尝试的代码如下:

boost::property_tree::ptree property_tree;
boost::property_tree::read_xml("config.xml", property_tree);
auto config = property_tree.get_child("Config");
std::chrono::nanoseconds duration_value = std::chrono::duration_cast<std::chrono::nanoseconds>(config.get<std::common_type<std::chrono::duration>>("DurationValue"));

这段代码无法工作,因为Boost.PropertyTree不知道如何将字符串转换为std::chrono::duration类型。请问有没有可行的实现方式?希望能灵活支持任意std::chrono字面量对应的单位,感谢!


解决方案

Boost.PropertyTree本身没有内置对std::chrono::duration类型的序列化/反序列化支持,需要自定义解析逻辑。核心思路是先读取字符串值,再手动解析其中的数值和单位,转换为目标的nanoseconds类型。

步骤1:实现字符串到nanoseconds的解析函数

编写通用函数处理常见时间单位(ns、us、ms、s、min、h等):

#include <chrono>
#include <string>
#include <stdexcept>
#include <cctype>

std::chrono::nanoseconds parse_duration(const std::string& str) {
    // 定位单位起始位置(跳过数字和小数点)
    size_t unit_pos = str.find_first_not_of("0123456789.");
    if (unit_pos == std::string::npos) {
        throw std::invalid_argument("Invalid duration: missing time unit");
    }

    // 拆分数值和单位
    double value = std::stod(str.substr(0, unit_pos));
    std::string unit = str.substr(unit_pos);

    // 转换为nanoseconds
    if (unit == "ns") {
        return std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::duration<double, std::nano>(value));
    } else if (unit == "us" || unit == "µs") {
        return std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::duration<double, std::micro>(value));
    } else if (unit == "ms") {
        return std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::duration<double, std::milli>(value));
    } else if (unit == "s") {
        return std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::duration<double>(value));
    } else if (unit == "min") {
        return std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::duration<double, std::ratio<60>>(value));
    } else if (unit == "h") {
        return std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::duration<double, std::ratio<3600>>(value));
    } else {
        throw std::invalid_argument("Unsupported time unit: " + unit);
    }
}

步骤2:结合Boost.PropertyTree使用该函数

读取ptree中的字符串值,传入解析函数即可:

#include <boost/property_tree/ptree.hpp>
#include <boost/property_tree/xml_parser.hpp>

int main() {
    boost::property_tree::ptree property_tree;
    boost::property_tree::read_xml("config.xml", property_tree);
    auto config = property_tree.get_child("Config");
    
    try {
        std::string duration_str = config.get<std::string>("DurationValue");
        std::chrono::nanoseconds duration_value = parse_duration(duration_str);
        // 后续使用duration_value
    } catch (const std::exception& e) {
        // 处理解析失败的情况
        std::cerr << "Failed to parse duration: " << e.what() << std::endl;
    }
    
    return 0;
}

进阶:注册自定义转换器(可选)

如果希望直接用config.get<std::chrono::nanoseconds>("DurationValue")的方式,可以注册Boost.PropertyTree的自定义转换器:

#include <boost/property_tree/translator_between.hpp>

namespace boost::property_tree {
    template <>
    struct translator_between<std::string, std::chrono::nanoseconds> {
        typedef translator_between<std::string, std::chrono::nanoseconds> type;

        std::chrono::nanoseconds get_value(const std::string& str) const {
            return parse_duration(str);
        }

        std::string put_value(const std::chrono::nanoseconds& dur) const {
            // 如需序列化,可在此实现反向转换(比如将nanoseconds转为带单位的字符串)
            return std::to_string(dur.count()) + "ns";
        }
    };
}

注册后即可直接调用:

std::chrono::nanoseconds duration_value = config.get<std::chrono::nanoseconds>("DurationValue");

注意事项

  • 解析函数支持浮点数和常见单位,如需支持更多单位(如天d),可自行扩展分支。
  • 建议添加异常捕获逻辑,处理无效数值、未知单位等错误场景。

内容的提问来源于stack exchange,提问作者SeedlessKiwi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.13 21:23:21