I wanted to have a good review on my code I wrote today to read files in C++ line by line. The file can look something like this:
# Program configuration
network.port=30000 # The port the server uses
network.ip=127.0.0.1 # The IP the server uses
Notes:
- Lines that start with
#
won't be processed - Lines that are empty won't be processed
- All the data before the
#
on a line will be processed - The data will be split by
=
, before the=
the key and after it the value
configuration.h:
#pragma once
#include <fstream>
#include <map>
#include <sstream>
class configuration
{
public:
configuration(const char* path);
~configuration();
std::string get_value(const char* key);
private:
std::map<std::string, std::string> values;
std::ifstream file;
};
configuration.cpp:
#include "configuration.h"
#include <Windows.h>
#include <iostream>
#include "logger.h"
configuration::configuration(const char* path)
{
try
{
file.open(std::string(path), std::ios::in);
values = std::map<std::string, std::string>();
if (file.is_open())
{
std::string line;
while (std::getline(file, line))
{
if (line.find("#") != 0 && !line.empty() && line.find("="))
{
std::string part = line.substr(0, line.find("#"));
std::string key = part.substr(0, line.find("="));
std::string value = part.substr(line.find("=") + 1);
values.insert_or_assign(key, value);
}
}
}
else
{
logger::log_error("File %s is not open!", path);
}
}
catch (const std::ios_base::failure& ex)
{
logger::log_error(ex.code().message().data());
}
}
std::string configuration::get_value(const char* key)
{
return values[key];
}
configuration::~configuration()
{
file.close();
}
Usage would be:
configuration* config = new configuration("file.cnf");
config->get_value("network.port");