C++简单配置文件程序(基于rapidjson)

本文介绍了一个用于读取、写入和管理配置文件的C++库,包括文件内容的读取、写入、访问检查、目录操作等功能,并使用了RapidJSON进行JSON数据解析与生成,适用于Windows和非Windows平台。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

#include <string>
#include <map>
#include <algorithm>

#ifdef _WIN32
#pragma warning(disable:4996)
#include <windows.h>
#include <io.h>
#include <shlwapi.h>
#pragma comment(lib, "shlwapi")
#endif 

#define  RAPIDJSON_HAS_STDSTRING 1
#include "rapidjson/document.h"
#include "rapidjson/writer.h"
#include "rapidjson/stringbuffer.h"
#include "rapidjson/reader.h"
#include "rapidjson/prettywriter.h"

using rapidjson::Document;
using rapidjson::StringBuffer;
using rapidjson::PrettyWriter;
using rapidjson::Value;

std::string readFileContent(const std::string &filename, bool isBinary, size_t limitSize, size_t beginIndex)
{
    FILE *f = fopen(filename.c_str(), "rb");
    if (f == NULL)
    {
        return "";
    }
    size_t fileLen = 0;
    fseek(f, 0, SEEK_SET);
    fileLen = ftell(f);
    fseek(f, 0, SEEK_END);
    fileLen = ftell(f) - fileLen;
    if (fileLen >= 3 && !isBinary && beginIndex == 0)
    {
        char buff[3];
        fread(buff, 1, 3, f);
        if ((unsigned char)buff[0] == 0xef
            && (unsigned char)buff[1] == 0xbb
            && (unsigned char)buff[2] == 0xbf)
        {
            beginIndex = 3;
        }
    }
    if (beginIndex >= fileLen)
    {
        fclose(f);
        return "";
    }
    if (limitSize > fileLen - beginIndex)
    {
        limitSize = fileLen - beginIndex;
    }

    fseek(f, (long)beginIndex, SEEK_SET);
    std::string ret;
    ret.resize(limitSize, '\0');
    size_t readLen = fread(&ret[0], 1, limitSize, f);
    fclose(f);
    if (readLen < limitSize)
    {
        return ret.substr(0, readLen);
    }
    return std::move(ret);
}

size_t writeFileContent(const std::string &filename, const char *buff, size_t buffLen, bool isAppend)
{
    std::string mod = "ab+";
    if (!isAppend)
    {
        mod = "wb+";
    }

    FILE *f = fopen(filename.c_str(), mod.c_str());
    if (f == NULL)
    {
        return 0;
    }
    size_t writeLen = fwrite(buff, 1, buffLen, f);
    fclose(f);
    return writeLen;
}

bool accessFile(const std::string &pathfile)
{
#ifdef _WIN32
    return ::_access(pathfile.c_str(), 0) == 0;
#else
    return ::access(pathfile.c_str(), F_OK) == 0;
#endif
}

bool isDirectory(const std::string & path)
{
#ifdef _WIN32
    return PathIsDirectoryA(path.c_str()) ? true : false;
#else
    DIR * pdir = opendir(path.c_str());
    if (pdir == NULL)
    {
        return false;
    }
    else
    {
        closedir(pdir);
        pdir = NULL;
        return true;
    }
#endif
}

bool createDirectory(std::string  path)
{
    if (path.empty()) return false;
    std::string sub;
    for (std::string::iterator iter = path.begin(); iter != path.end(); ++iter)
    {
        if (*iter == '\\') { *iter = '/'; }
    }
    if (path.at(path.length() - 1) != '/') { path.append("/"); }

    std::string::size_type pos = path.find('/');
    while (pos != std::string::npos)
    {
        std::string cur = path.substr(0, pos - 0);
        if (cur.length() > 0 && !isDirectory(cur))
        {
            bool ret = false;
#ifdef WIN32
            ret = CreateDirectoryA(cur.c_str(), NULL) ? true : false;
#else
            ret = (mkdir(cur.c_str(), S_IRWXU | S_IRWXG | S_IRWXO) == 0);
#endif
            if (!ret)
            {
                return false;
            }
        }
        pos = path.find('/', pos + 1);
    }
    return true;
}


std::string g_config_file_name="./config/config";

void setConfigFile(const std::string &file_name)
{
    g_config_file_name = file_name;
    auto ret = g_config_file_name;
    std::for_each(ret.begin(), ret.end(), [](char &ch) { if (ch == '\\') ch = '/'; });
    auto pos=ret.find_last_of('/');
    auto path = ret.substr(0, pos);
    if (!isDirectory(path))createDirectory(path);
}

std::string getConfig(const std::string &key)
{
    std::string content = readFileContent(g_config_file_name, false, 1024 * 1024, 0);
    if (content == "")return "";
    Document doc;
    doc.Parse(content);
    if (doc.HasParseError())return "";
    std::map<std::string, std::string> params;
    if (doc.HasMember("config") && doc["config"].IsArray())
    {
        for (auto &p : doc["config"].GetArray())
        {
            params.insert(std::make_pair(p["name"].GetString(), p["value"].GetString()));
        }
        if (params.find(key) != params.end())return params[key];
        else return "";
    }
    else return "";
}

void setConfig(const std::string &key, const std::string &value)
{
    auto ret = g_config_file_name;
    std::for_each(ret.begin(), ret.end(), [](char &ch) { if (ch == '\\') ch = '/'; });
    auto pos = ret.find_last_of('/');
    auto path = ret.substr(0, pos);
    if (!isDirectory(path))createDirectory(path);

    std::string content = readFileContent(g_config_file_name, false, 1024 * 1024, 0); 

    Document doc;
    doc.Parse(content);
    if (content == "" || doc.HasParseError())
    {
        //新建
        Document doc_new(rapidjson::kObjectType);
        Value v(rapidjson::kArrayType);
        Value tmp(rapidjson::kObjectType);
        tmp.AddMember("name", key, doc.GetAllocator());
        tmp.AddMember("value", value, doc.GetAllocator());
        v.PushBack(tmp, doc.GetAllocator());
        doc_new.AddMember("config", v, doc.GetAllocator());
        StringBuffer buffer;
        PrettyWriter<StringBuffer> writer(buffer);
        doc_new.Accept(writer);
        std::string res(buffer.GetString());
        writeFileContent(g_config_file_name, res.data(), res.size(), false);
    }
    else
    {
        std::map<std::string, std::string> params;
        if (doc.HasMember("config") && doc["config"].IsArray())
        {
            for (auto &p : doc["config"].GetArray())
            {
                params.insert(std::make_pair(p["name"].GetString(), p["value"].GetString()));
            }
        }
        
        params[key] = value;

        Document doc_new(rapidjson::kObjectType);
        Value v(rapidjson::kArrayType);
        for (const auto &p : params) {
            Value tmp(rapidjson::kObjectType);
            tmp.AddMember("name", p.first, doc.GetAllocator());
            tmp.AddMember("value", p.second, doc.GetAllocator());
            v.PushBack(tmp, doc.GetAllocator());
        }
        doc_new.AddMember("config", v, doc.GetAllocator());
        StringBuffer buffer;
        PrettyWriter<StringBuffer> writer(buffer);
        doc_new.Accept(writer);
        std::string res(buffer.GetString());
        writeFileContent(g_config_file_name, res.data(), res.size(), false);

    }

}
#pragma once

#ifndef _LIB_CONFIG_H_
#define _LIB_CONFIG_H_
#include <string>

void setConfigFile(const std::string &file_name);
std::string getConfig(const std::string &key);
void setConfig(const std::string &key, const std::string &value);

#endif // _LIB_CONFIG_H_


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值