如何使用 yaml-cpp 修改值?

How to modify a value with yaml-cpp?

我正在尝试为我的应用程序制作配置文件,为此我使用 yaml-cpp 库生成配置并在用户更改应用程序中的某些设置或某些内容时进行修改。我为此设置了一个单独的 class,构造函数生成 yaml 文件,如下所示,

Serializer::Serializer(const std::string& filepath)
{
    std::ifstream ifin(filepath);

    if (!ifin)
    {
        emitter << YAML::Comment("Hello");
        emitter << YAML::BeginDoc;
        emitter << "This is the configuration file for the Sample Browser,"
                << YAML::Newline;
        emitter << "feel free to edit this file as needed";
        emitter << YAML::EndDoc;

        emitter << YAML::BeginMap;

        emitter << YAML::Newline << YAML::Key << "Window";
        emitter << YAML::BeginMap;
        emitter << YAML::Key << "SizeW" << YAML::Value << "1280";
        emitter << YAML::Key << "SizeH" << YAML::Value << "720";
        emitter << YAML::EndMap << YAML::Newline;

        emitter << YAML::Newline << YAML::Key << "Media";
        emitter << YAML::BeginMap;
        emitter << YAML::Key << "Autoplay" << YAML::Value << "false";
        emitter << YAML::Key << "Loop" << YAML::Value << "false";
        emitter << YAML::Key << "Muted" << YAML::Value << "false";
        emitter << YAML::EndMap << YAML::Newline;

        emitter << YAML::Newline << YAML::Key << "Display";
        emitter << YAML::BeginMap;
        emitter << YAML::Key << "Font";
        emitter << YAML::BeginMap;
        emitter << YAML::Key << "Family" << YAML::Value << "Sans";
        emitter << YAML::Key << "Size" << YAML::Value << "10";
        emitter << YAML::EndMap;
        emitter << YAML::EndMap << YAML::Newline;

        emitter << YAML::Newline << YAML::Key << "Import_dir";
        emitter << YAML::BeginMap;
        emitter << YAML::Key << "AutoImport" << YAML::Value << "false";
        emitter << YAML::Key << "Directory" << YAML::Value << "/home/apoorv";
        emitter << YAML::EndMap << YAML::Newline;

        emitter << YAML::EndMap;

        std::ofstream ofout(filepath);
        ofout << emitter.c_str();
    }
    else
    {
        wxLogDebug("Config file already exists! Skipping..");
    }
}

这个文件的输出看起来像,

# Hello
---
This is the configuration file for the Sample Browser,
feel free to edit this file as needed
...

Window:
  SizeW: 1280
  SizeH: 720

Media:
  Autoplay: false
  Loop: false
  Muted: false

Display:
  Font:
    Family: "Sans"
    Size: "10"

Import_dir:
  AutoImport: false
  Directory: "/home/apoorv/"

我希望当用户更改字体时,相关的键值也会随着所选选项的变化而变化。我尝试制作一个应该这样做的函数,

void Serializer::SerializeDisplaySettings(const std::string& filepath, wxFont& font)
{
    YAML::Emitter out;

    std::string fontFace = font.GetFaceName().ToStdString();
    int fontSize = font.GetPointSize();

    std::ifstream ifin(filepath);

    try
    {
        YAML::Node config = YAML::LoadAllFromFile(filepath)[1];

        auto display = config["Display"];

        if (auto fontSetting = display["Font"])
        {
            wxLogDebug("Changing font settings");
            wxLogDebug("Font face: %s", fontFace);
            wxLogDebug("Font size: %d", fontSize);

            out << YAML::Key << fontSetting["Family"] << YAML::Value << fontFace;
            out << YAML::Key << fontSetting["Size"] << YAML::Value << fontSize;

            std::ofstream ofout(filepath);
            ofout << out.c_str();
        }
        else
        {
            wxLogDebug("Error! Cannot fetch values.");
        }
    }

    catch(const YAML::ParserException& ex)
    {
        std::cout << ex.what() << std::endl;
    }
}

但这会删除整个内容并仅填充字体名称和大小。如何在没有 changing/deleting 整个文件的情况下修改这些值?

你覆盖文件,当然它只包含你给发射器的项目out。如果你想修改加载的文件,你应该更新 config 中的值并将其全部写回:

fontSetting["Family"] = fontFace;
fontSetting["Size"] = fontSize;
out << config;
std::ofstream ofout(filepath);
ofout << out.c_str();

要同时获取其他内容,请在加载时执行此操作:

auto docs = YAML::LoadAllFromFile(filepath);
out << YAML::Comment("Hello") << YAML::BeginDoc << docs[0] << YAML::EndDoc;
YAMl::Node config = docs[1];