한 번만 더 해보자

[C++] config 파일 읽기 및 수정 본문

언어/C C++

[C++] config 파일 읽기 및 수정

정 하임 2024. 5. 30. 22:02

단순 .ini 형식의 config 파일 읽기

config 파일 형식

ini코드 복사
[Database]
user = root
password = rootpassword
host = localhost
port = 3306

 

 

C++ 코드

#include <iostream>
#include <fstream>
#include <sstream>
#include <string>
#include <map>


// Config 파일을 파싱하는 함수
std::map<std::string, std::string> parseConfigFile(const std::string &filename) {
    std::ifstream file(filename);
    std::map<std::string, std::string> config;
    std::string line;

    if (!file.is_open()) {
        throw std::runtime_error("Could not open config file");
    }

    std::string section;
    while (std::getline(file, line)) {
        // 공백 및 주석 무시
        line.erase(0, line.find_first_not_of(" \\t"));
        if (line.empty() || line[0] == ';' || line[0] == '#') continue;

        // 섹션 처리
        if (line[0] == '[') {
            section = line.substr(1, line.find(']') - 1);
            continue;
        }

        // key-value 쌍 파싱
        std::size_t delimiterPos = line.find('=');
        if (delimiterPos != std::string::npos) {
            std::string key = line.substr(0, delimiterPos);
            std::string value = line.substr(delimiterPos + 1);

            // 공백 제거
            key.erase(key.find_last_not_of(" \\t") + 1);
            key.erase(0, key.find_first_not_of(" \\t"));
            value.erase(value.find_last_not_of(" \\t") + 1);
            value.erase(0, value.find_first_not_of(" \\t"));

            config[section + "." + key] = value;
        }
    }

    file.close();
    return config;
}

int main() {
    try {
        auto config = parseConfigFile("config.ini");

        // 예시: config 값 출력
        std::cout << "Database User: " << config["Database.user"] << std::endl;
        std::cout << "Database Password: " << config["Database.password"] << std::endl;
        std::cout << "Database Host: " << config["Database.host"] << std::endl;
        std::cout << "Database Port: " << config["Database.port"] << std::endl;
    } catch (const std::exception &e) {
        std::cerr << "Error: " << e.what() << std::endl;
        return 1;
    }

    return 0;
}

 

 

 

Config 파일 읽기 및 쓰기

#include <iostream>
#include <fstream>
#include <sstream>
#include <string>
#include <map>
#include <stdexcept>



// Config 파일을 파싱하는 함수
std::map<std::string, std::string> parseConfigFile(const std::string &filename) {
    std::ifstream file(filename);
    std::map<std::string, std::string> config;
    std::string line;

    if (!file.is_open()) {
        throw std::runtime_error("Could not open config file");
    }

    std::string section;
    while (std::getline(file, line)) {
        // 공백 및 주석 무시
        line.erase(0, line.find_first_not_of(" \\t"));
        if (line.empty() || line[0] == ';' || line[0] == '#') continue;

        // 섹션 처리
        if (line[0] == '[') {
            section = line.substr(1, line.find(']') - 1);
            continue;
        }

        // key-value 쌍 파싱
        std::size_t delimiterPos = line.find('=');
        if (delimiterPos != std::string::npos) {
            std::string key = line.substr(0, delimiterPos);
            std::string value = line.substr(delimiterPos + 1);

            // 공백 제거
            key.erase(key.find_last_not_of(" \\t") + 1);
            key.erase(0, key.find_first_not_of(" \\t"));
            value.erase(value.find_last_not_of(" \\t") + 1);
            value.erase(0, value.find_first_not_of(" \\t"));

            config[section + "." + key] = value;
        }
    }

    file.close();
    return config;
}

// Config 파일을 저장하는 함수
void saveConfigFile(const std::string &filename, const std::map<std::string, std::string> &config) {
    std::ofstream file(filename);
    if (!file.is_open()) {
        throw std::runtime_error("Could not open config file for writing");
    }

    std::string currentSection;
    for (const auto &kv : config) {
        std::string key = kv.first;
        std::string value = kv.second;

        // 섹션을 추출
        std::size_t dotPos = key.find('.');
        if (dotPos != std::string::npos) {
            std::string section = key.substr(0, dotPos);
            key = key.substr(dotPos + 1);

            // 섹션이 변경되면 섹션 헤더를 파일에 씁니다
            if (section != currentSection) {
                if (!currentSection.empty()) file << "\\n";
                currentSection = section;
                file << "[" << section << "]\\n";
            }
        }

        file << key << " = " << value << "\\n";
    }

    file.close();
}

// Config 값을 수정하는 함수
void modifyConfigValue(std::map<std::string, std::string> &config, const std::string &key, const std::string &value) {
    config[key] = value;
}

int main() {
    try {
        // config 파일 읽기
        auto config = parseConfigFile("config.ini");

        // 값 수정
        modifyConfigValue(config, "Database.user", "new_user");
        modifyConfigValue(config, "Database.password", "new_password");

        // 수정된 config 파일 저장
        saveConfigFile("config.ini", config);

        std::cout << "Config file updated successfully." << std::endl;
    } catch (const std::exception &e) {
        std::cerr << "Error: " << e.what() << std::endl;
        return 1;
    }

    return 0;
}

 

 

 

반응형

'언어 > C C++' 카테고리의 다른 글

[C++] invalid conversion from ‘const char*’ to ‘char*’  (0) 2024.09.26