在平常的软件开发过程中,配置文件是重要的一环,使用配置文件在软件开发过程中具有以下好处和必要性:
- 灵活性:配置文件允许在不修改代码的情况下更改应用程序的行为,通过修改配置文件,可以调整应用程序的参数、设置和选项,以满足不同的需求和环境。
- 可维护性:将配置信息从代码中分离出来,使得维护和管理变得更加容易,当需要修改配置时,只需修改配置文件,而不需要重新编译和部署整个应用程序。
- 可扩展性:配置文件可以用于支持应用程序的扩展。通过添加新的配置项,可以轻松地引入新的功能或模块,而无需修改现有的代码。
- 跨环境部署 :使用配置文件可以轻松地在不同的环境中部署应用程序,例如开发、测试和生产环境,通过切换不同的配置文件,可以适应不同环境的需求。
总之,配置文件在软件开发中起到了关键的作用,它们提供了一种灵活、可维护和可扩展的方式来管理应用程序的行为和设置。
虽然写配置文件本身是一个简单的事情,但很容易出错,且容易因为规范不一导致解析出错,自从使用了TOML库,发现是真香!
1.关于toml
toml11是一个C++的库,用于解析和生成 TOML(Tom's Obvious, Minimal Language)格式的配置文件。TOML是一种易于阅读和编写的配置文件格式,被广泛用于各种应用程序的配置文件中。主要作用是提供了一种简单、高效的方式来读取和写入TOML格式的配置文件。
源码:
https://github.com/marzer/tomlplusplus
https://github.com/ToruNiina/toml11
https://gitee.com/boss-dog/tomlplusplus
https://gitee.com/boss-dog/toml11
toml11和tomlplusplus都是C++的库,用于解析和生成TOML格式的配置文件。
toml11是一个轻量级的TOML库,可以直接包含在项目中使用,无需额外的依赖,代码量较小,功能相对较少,但足以满足大多数简单的TOML文件解析和生成需求。
tomlplusplus是一个更为全面和功能丰富的TOML库,它是基于toml11的基础上进行扩展和改进的,支持更多的TOML语法特性,提供了更灵活的配置选项和更强大的错误处理机制。
总的来说,toml11适用于简单的TOML文件解析和生成需求,它轻量、易用、快速。而tomlplusplus则适用于更复杂的TOML文件操作,提供了更多的功能和选项,并具有更好的性能。选择使用哪个库取决于具体的需求和项目的规模。
1.1 安装toml
- 1.从toml11的仓库下载源代码
bash
git clone https://gitee.com/boss-dog/toml11.git
-
2.将下载的源代码放置在项目目录中的合适位置。
-
3.在CMakeLists.txt文件中添加以下内容,以引入toml11库:
powershell
# 设置toml11库的路径
set(TOML11_INCLUDE_DIR /path/to/toml11)
# 添加toml11库的头文件路径
include_directories(${TOML11_INCLUDE_DIR})
# 添加toml11库的源文件
add_library(toml11 INTERFACE)
target_include_directories(toml11 INTERFACE ${TOML11_INCLUDE_DIR})
请确保将/path/to/toml11
替换为实际的toml11库的路径。
- 在项目中可以使用
#include "toml.hpp"
来包含toml11库的头文件,并使用toml::前缀来访问toml11库的功能
2.示例:使用toml库编写对配置文件的解析
dog_roster.conf
xml
num_dog = 3
version = '1.1.2'
[[Zhou]]
name = 'BuDing'
adopted = true
age = 4
weight = 15.6
height = 30.0
[Zhou.options]
pose = [0.1,0.2,0.3]
[[Zhou]]
name = 'DuoDuo'
adopted = true
age = 3.5
weight = 15.6
height = 29.8
[Zhou.options]
pose = [1.1,1.2,1.3]
[[Zhou]]
name = 'PaoPao'
adopted = false
age = 6
weight = 28.2
height = 50.1
[Zhou.options]
pose = [0.01,0.02,0.03]
CMakeLists.txt
powershell
cmake_minimum_required(VERSION 3.16)
project(MyDemo)
# 设置C++标准
set(CMAKE_CXX_STANDARD 17)
# 设置toml11库的路径
set(TOML11_INCLUDE_DIR toml11)
# 添加toml11库的头文件路径
include_directories(${TOML11_INCLUDE_DIR})
# 添加可执行文件
add_executable(test_toml
test_toml.cpp
)
# 添加toml11库的源文件
add_library(toml11 INTERFACE)
target_include_directories(test_toml INTERFACE ${TOML11_INCLUDE_DIR})
test_toml.cpp
cpp
#include <iostream>
#include "toml.hpp"
int main()
{
// 解析配置文件
std::ifstream config_file("../dog_roster.conf");
if (!config_file.is_open()) {
std::cerr << "Failed to open config file!" << std::endl;
return -1;
}
const auto data = toml::parse(config_file);
// 获取num_dog和version的值
const int num_dog = toml::find<int>(data, "num_dog");
const std::string version = toml::find<std::string>(data, "version");
std::cout << "num_dog: " << num_dog << std::endl;
std::cout << "version: " << version << std::endl;
try {
// 遍历每个狗的信息
const auto &dogs = toml::find(data, "Zhou");
for (const auto &dog : dogs.as_array()) {
const std::string name = toml::find<std::string>(dog, "name");
const bool adopted = toml::find<bool>(dog, "adopted");
int age = -1;
if (dog.at("age").is_integer()) {
age = toml::find<int>(dog, "age");
} else if (dog.at("age").is_floating()) {
age = toml::find<double>(dog, "age");
}
const double weight = toml::find<double>(dog, "weight");
const double height = toml::find<double>(dog, "height");
std::cout << "name: " << name << std::endl;
std::cout << "adopted: " << (adopted ? "true" : "false")
<< std::endl;
std::cout << "age: " << age << std::endl;
std::cout << "weight: " << weight << std::endl;
std::cout << "height: " << height << std::endl;
// 获取pose选项的值
const auto &options = toml::find(dog, "options");
const auto pose = toml::find<std::vector<double>>(options, "pose");
std::cout << "pose: [";
for (const auto &p : pose) {
std::cout << p << ", ";
}
std::cout << "]" << std::endl;
}
} catch (const toml::syntax_error &e) {
std::cerr << "Syntax error in configuration file: " << e.what()
<< std::endl;
} catch (const std::exception &e) {
std::cerr << "Error occurred: " << e.what() << std::endl;
}
std::cout << "Finished!" << std::endl;
return 0;
}