Project Icon

mINI

简化C++ INI文件操作的轻量级头文件库

mINI是一个专门用于操作INI文件的C++头文件库。它具有轻量级、易用性强的特点,支持大小写不敏感的节和键名,忽略空白字符,允许空节和键名,并支持注释。该库采用懒写入方式,只更新变更部分,保留原有格式和注释。mINI提供了简洁的API用于读取、写入和生成INI文件,支持数据结构遍历,并可选择是否区分大小写。这个库为开发者提供了一种高效、灵活的方式来处理INI配置文件。

mINI

v0.9.16

信息

这是一个用于操作INI文件的小型仅有头文件的C++库。

它遵循以下格式:

  • 默认情况下,区段和键名称不区分大小写
  • 忽略区段、键和值周围的空白字符
  • 允许使用空的区段和键名称
  • 不属于任何区段的键将被忽略
  • 注释是以分号(;)作为第一个非空白字符的行
  • 在区段行上允许有尾部注释,但在键/值行上不允许
  • 每个条目都在单独的一行上,不支持多行
; 注释
[区段]
键 = 值

文件是按需一次性读取的,之后数据保存在内存中并可以进行操作。读写操作后,文件会被关闭。此实用程序支持延迟写入,只写入更改和更新,并保留自定义格式和注释。由write()调用触发的延迟写入会读取输出文件,找出已经进行的更改,并相应地更新文件。如果你只需要生成文件,请使用generate()

读取和写入操作时,区段和键的顺序会被保留。遍历数据时,顺序将与原始文件或添加到结构中的键的顺序相同。

该库使用std::string类型保存值,并依赖于您的主机环境的编码。它应该能很好地处理UTF-8,但实际效果可能会有所不同。

安装

这是一个头文件库。要安装它,只需将/src/中的所有内容复制到你自己项目的源代码文件夹中,或使用自定义位置,并确保你的编译器能看到额外的include目录。然后在你的代码中包含该文件:

#include "mini/ini.h"

就这么简单!

基本示例

读取/写入

从名为myfile.ini的INI文件开始:

; 水果数量
[水果]
苹果=20
橙子=30

我们的代码:

// 首先,创建一个文件实例
mINI::INIFile file("myfile.ini");

// 接下来,创建一个用于保存数据的结构
mINI::INIStructure ini;

// 现在我们可以读取文件
file.read(ini);

// 读取值
std::string& 苹果数量 = ini["水果"]["苹果"];

// 更新一个值
ini["水果"]["橙子"] = "50";

// 添加一个新条目
ini["水果"]["香蕉"] = "100";

// 将更新写入文件
file.write(ini);

运行代码后,我们的INI文件现在看起来像这样:

; 水果数量
[水果]
苹果=20
橙子=50
香蕉=100

生成一个文件

// 创建一个文件实例
mINI::INIFile file("myfile.ini");

// 创建一个数据结构
mINI::INIStructure ini;

// 填充结构
ini["物品"]["椅子"] = "20";
ini["物品"]["气球"] = "100";

// 生成一个INI文件(覆盖任何以前的文件)
file.generate(ini);

操作文件

INIFile类保持文件名,并公开读取、写入和生成INI文件的函数。它不会保持文件打开,而只是提供一个可以用来访问物理文件的抽象。

创建一个文件实例:

mINI::INIFile file("myfile.ini");

您还需要一个可以操作的结构:

mINI::INIStructure ini;

读取文件:

bool readSuccess = file.read(ini);

在保留注释和自定义格式的情况下写回文件:

bool writeSuccess = file.write(ini);

您可以将第二个参数设置为true,以便以漂亮的格式写入文件:

bool writeSuccess = file.write(ini, true);

write()调用将尝试保留原始INI文件的任何自定义格式,并仅为新建的键和区段使用漂亮的格式。

生成一个文件:

file.generate(ini);

请注意,generate()将覆盖原始文件中的任何自定义格式和注释!

您也可以将漂亮的格式与generate()一起使用:

file.generate(ini, true);

不带漂亮格式的生成INI文件示例输出:

[section1]
key1=value1
key2=value2
[section2]
key1=value1

带有漂亮格式的生成INI文件示例输出:

[section1]
key1 = value1
key2 = value2

[section2]
key1 = value1

操作数据

读取数据

有两种方式可以从INI结构中读取数据。您可以使用[]运算符或get()函数:

// 读取值 - 如果键或区段不存在,它们将被创建
// 返回对真实值的引用
std::string& 值 = ini["区段"]["键"];

// 安全地读取值 - 如果键或区段不存在,它们将不会被创建
// 返回值的副本
std::string 值 = ini.get("区段").get("键");

[]get()操作的区别在于,[]返回对真实数据的引用(您可以修改),并在不存在时自动创建新项,而get()返回数据的副本,不会在结构中创建新项。如果您希望避免改变结构,请在使用[]之前使用has()

您可以结合使用[]get()。 章节名称和键名称不区分大小写,并且会删除前后的空白字符。ini["section"]ini["SECTION"]ini[" sEcTiOn "]等价。生成的文件始终使用小写表示章节名称和键名称。写入现有文件时,如果章节名称或键名称已存在,将保留原文件中的大小写。

更新数据

设置或更新值的方式如下:

ini["section"]["key"] = "value";

注意,写入文件时,值会被删除前后的空白字符。例如,以下值在从文件中读取时将被转换为"c": ini["a"]["b"] = " c ";

你可以使用set()一次设置多个值:

ini["section"].set({
    {"key1", "value1"},
    {"key2", "value2"}
});

创建一个空章节:

ini["section"];

类似地,创建一个空键:

ini["section"]["key"];

删除某个章节的单个键:

bool removeSuccess = ini["section"].remove("key");

删除整个章节:

bool removeSuccess = ini.remove("section");

删除某个章节的所有键:

ini["section"].clear();

删除结构中的所有数据:

ini.clear();

其他功能

检查是否存在某个章节:

bool hasSection = ini.has("section");

检查某个章节中是否存在某个键:

bool hasKey = ini["section"].has("key");

获取某个章节中键的数量:

size_t n_keys = ini["section"].size();

获取结构中章节的数量:

size_t n_sections = ini.size();

注意事项

请注意,[]操作符将始终创建一个新项,如果该项不存在的话!你可以使用has()检查项是否存在,然后再执行进一步操作。记住,get()将返回数据的副本,所以你不应该使用它来执行删除或更新操作!

在大多数现实场景中,使用[]操作符并不会有问题,因为你通常会查找已知的键,并且可能不关心是否创建了空键或章节。但是,如果你有一个场景不希望向结构添加新项,要么使用get()来获取项,要么在使用[]操作符之前使用has()检查项是否存在,以确保安全操作。

下面是一个安全操作数据的示例:

if (ini.has("section"))
{
    // 我们有这个章节,可以安全访问它而不创建新章节
    auto& collection = ini["section"];
    if (collection.has("key"))
    {
        // 我们有这个键,可以安全访问它而不创建新键
        auto& value = collection["key"];
    }
}

遍历

你可以按插入顺序遍历整个结构。下面的示例循环遍历结构并以熟悉的格式显示结果:

for (auto const& it : ini)
{
    auto const& section = it.first;
    auto const& collection = it.second;
    std::cout << "[" << section << "]" << std::endl;
    for (auto const& it2 : collection)
    {
        auto const& key = it2.first;
        auto const& value = it2.second;
        std::cout << key << "=" << value << std::endl;
    }
}

it.first类型始终为std::string

it.second是一个对象,在第一层为mINI::INIMap类型,在第二层为std::string类型。

API只公开了const_iterator,所以你不能直接使用迭代器来修改数据。但是,你可以在遍历时正常访问该结构:

// 将结构中所有值更改为"banana"
for (auto const& it : ini)
{
    auto const& section = it.first;
    auto const& collection = it.second;
    for (auto const& it2 : collection)
    {
        auto const& key = it2.first;
        ini[section][key] = "banana"; // O(1)因为使用哈希表
    }
}

区分大小写

如果你希望该库不忽略大小写,请在包含库之前添加指令#define MINI_CASE_SENSITIVE:

#define MINI_CASE_SENSITIVE
#include "mini/ini.h"

这将影响从文件读取和写入,以及对结构的访问。

鸣谢

  • lest - 测试框架

许可证

版权所有 © 2018 Danijel Durakovic

根据MIT许可证的条款获得许可

项目侧边栏1项目侧边栏2
推荐项目
Project Cover

豆包MarsCode

豆包 MarsCode 是一款革命性的编程助手,通过AI技术提供代码补全、单测生成、代码解释和智能问答等功能,支持100+编程语言,与主流编辑器无缝集成,显著提升开发效率和代码质量。

Project Cover

AI写歌

Suno AI是一个革命性的AI音乐创作平台,能在短短30秒内帮助用户创作出一首完整的歌曲。无论是寻找创作灵感还是需要快速制作音乐,Suno AI都是音乐爱好者和专业人士的理想选择。

Project Cover

有言AI

有言平台提供一站式AIGC视频创作解决方案,通过智能技术简化视频制作流程。无论是企业宣传还是个人分享,有言都能帮助用户快速、轻松地制作出专业级别的视频内容。

Project Cover

Kimi

Kimi AI助手提供多语言对话支持,能够阅读和理解用户上传的文件内容,解析网页信息,并结合搜索结果为用户提供详尽的答案。无论是日常咨询还是专业问题,Kimi都能以友好、专业的方式提供帮助。

Project Cover

阿里绘蛙

绘蛙是阿里巴巴集团推出的革命性AI电商营销平台。利用尖端人工智能技术,为商家提供一键生成商品图和营销文案的服务,显著提升内容创作效率和营销效果。适用于淘宝、天猫等电商平台,让商品第一时间被种草。

Project Cover

吐司

探索Tensor.Art平台的独特AI模型,免费访问各种图像生成与AI训练工具,从Stable Diffusion等基础模型开始,轻松实现创新图像生成。体验前沿的AI技术,推动个人和企业的创新发展。

Project Cover

SubCat字幕猫

SubCat字幕猫APP是一款创新的视频播放器,它将改变您观看视频的方式!SubCat结合了先进的人工智能技术,为您提供即时视频字幕翻译,无论是本地视频还是网络流媒体,让您轻松享受各种语言的内容。

Project Cover

美间AI

美间AI创意设计平台,利用前沿AI技术,为设计师和营销人员提供一站式设计解决方案。从智能海报到3D效果图,再到文案生成,美间让创意设计更简单、更高效。

Project Cover

AIWritePaper论文写作

AIWritePaper论文写作是一站式AI论文写作辅助工具,简化了选题、文献检索至论文撰写的整个过程。通过简单设定,平台可快速生成高质量论文大纲和全文,配合图表、参考文献等一应俱全,同时提供开题报告和答辩PPT等增值服务,保障数据安全,有效提升写作效率和论文质量。

投诉举报邮箱: service@vectorlightyear.com
@2024 懂AI·鲁ICP备2024100362号-6·鲁公网安备37021002001498号