Is there a class file or built in functions to handle ini/inf files? I had made one but it's kind of slow when it comes to reading large files ( 2MB+ ).
Printable View
Is there a class file or built in functions to handle ini/inf files? I had made one but it's kind of slow when it comes to reading large files ( 2MB+ ).
No. Nothing built in to handle ini''s.
If you post the code for yours here, I'm sure some of us can find ways to optimize it. 2 million bytes isn't a lot in the grand scheme of things, if there's like 10 characters per line, that's only 200,000 entries. There should be no issue getting through that...though I do have to ask, what the hell is using an ini that large?
Since most systems are multi-core/proc, depending on what this is going into, you might want to think about threading it, and starting a second thread half way down the list or something...but chance are there's room for optimization in yours.
It's not complete but here goes
IniEditor.h
Code:#ifndef INIEDITOR_H
#define INIEDITOR_H
#include <vector>
#include <fstream>
#include <string>
#include <iostream>
#include <algorithm>
#include <iterator>
#include <cstdlib>
using namespace std;
class Section
{
public:
Section(string name);
//Section(char name[]);
void addOption(string key, string value);
void removeOption(string key);
//void updateValue(string key, string value);
string getSectionName();
void display();
std::vector<string> getOptions();
string getValue(string option);
bool exists(string option);
private:
string secName;
std::vector<string> key;
std::vector<string> value;
int getOptionPosition(string option);
string fix(string str);
};
class IniEditor
{
public:
IniEditor();
IniEditor(string filename);
~IniEditor();
bool load(string filename);
string toString();
void displaySections();
void display(string sectionname);
void removeOption(string sectionname, string key);
void save();
bool hasSection(string sectionname);
bool hasOption(string sectionname, string option);
//void removeSection(string sectionname);
//void addSection(string sectionname);
private:
string filename;
std::vector<Section> sections;
bool contains(char c[], char character, int size);
string IniEditor::parseSectionHeader(char c[], int size);
string IniEditor::parseSectionHeader(std::string &c);
vector<string> IniEditor::StringSplit(string str, string delim);
string getSectionHeaderFormatted(string sectionname);
int getSectionPosition(string sectionname);
int Get_Size(string path);
};
#endif
IniEditor.cpp
Code:#include "IniEditor.h"
#include <Windows.h>
IniEditor::IniEditor()
{
this->filename = "";
}
IniEditor::IniEditor(string filename)
{
this->filename = filename;
load(filename);
}
IniEditor::~IniEditor()
{
}
bool IniEditor::load(string filename)
{
this->filename = filename;
ifstream ini;
ini.open(filename, std::ios::in);
char buffer[1024];
string parse;
if(ini)
{
while (!ini.eof())
{
for (int i = 0; i < 1024; i++)
buffer[i] = ' ';
ini.getline(buffer, 1024, '\n');
if (this->contains(buffer, '[', 1024) && this->contains(buffer, ']', 1024))
{
sections.push_back(Section(parseSectionHeader(buffer, 1024)));
}
else
{
if (buffer[1] != ' ' && buffer[0] != '\n' && buffer[0] != ';')
{
parse = buffer;
vector<string> temp;
temp = StringSplit(parse, "=");
sections[sections.size() - 1].addOption(temp[0], temp[1]);
}
}
}
ini.close();
}
return true;
}
bool IniEditor::contains(char c[], char character, int size)
{
for (int i = 0; i < size; i++)
{
if (c[i] == character)
return true;
}
return false;
}
string IniEditor::parseSectionHeader(std::string &c)
{
char * s = (char *)(malloc(sizeof(char) * c.length()));
strcpy(s, c.c_str());
return(parseSectionHeader(s, sizeof(s)));
}
string IniEditor::parseSectionHeader(char c[], int size)
{
string temp = "";
bool start = false, done = false;
for (int i = 0; i < size && !done; i++)
{
if (start == true)
{
if (c[i] != ']')
{
temp += c[i];
}
else
{
temp += c[i];
done = true;
}
}
else if(c[i] == '[')
{
start = true;
temp += c[i];
}
}
return temp;
}
string IniEditor::toString()
{
return this->filename;
}
vector<string> IniEditor::StringSplit(string str, string delim)
{
vector<string> results;
int cutAt;
while( (cutAt = str.find_first_of(delim)) != str.npos )
{
if(cutAt > 0)
{
results.push_back(str.substr(0,cutAt));
}
str = str.substr(cutAt+1);
}
if(str.length() > 0)
{
results.push_back(str);
}
return results;
}
void IniEditor::removeOption(string sectionname, string key)
{
sectionname = getSectionHeaderFormatted(sectionname);
int pos = getSectionPosition(sectionname);
if (pos >= 0)
sections[getSectionPosition(sectionname)].removeOption(key);
}
void IniEditor::displaySections()
{
for (int i = 0; i < sections.size(); i++)
{
cout << sections[i].getSectionName() << endl;
sections[i].display();
cout << "\n\n";
}
}
void IniEditor::display(string sectionname)
{
sectionname = getSectionHeaderFormatted(sectionname);
int pos = getSectionPosition(sectionname);
if (pos >= 0)
sections[pos].display();
}
int IniEditor::getSectionPosition(string sectionname)
{
int i = 0;
for (; i < sections.size(); i++)
{
if (strcmp(sections[i].getSectionName().c_str(), sectionname.c_str()) == 0)
{
return i;
}
}
i = -1;
return i;
}
string IniEditor::getSectionHeaderFormatted(string sectionname)
{
if (sectionname.at(0) != '[')
{
sectionname = "[" + sectionname + "]";
}
return sectionname;
}
void IniEditor::save()
{
ofstream ini;
ini.open(this->filename);
if (ini)
{
for (int count = 0; count < sections.size(); count++)
{
ini << sections[count].getSectionName() << endl;
std::vector<string> options = sections[count].getOptions();
for (int i = 0; i < options.size(); i++)
{
ini << options[i] << " = " << sections[count].getValue(options[i]) << endl;
}
ini << endl;
}
ini.close();
}
}
bool IniEditor::hasSection(string sectionname)
{
if (getSectionPosition(getSectionHeaderFormatted(sectionname)) >= 0)
return true;
return false;
}
bool IniEditor::hasOption(string sectionname, string option)
{
int pos = getSectionPosition(getSectionHeaderFormatted(sectionname));
if (pos >= 0)
return (sections[pos].exists(option));
return false;
}
int IniEditor::Get_Size( string path )
{
FILE *pFile = NULL;
fopen_s( &pFile, path.c_str(), "rb" );
fseek( pFile, 0, SEEK_END );
int Size = ftell( pFile );
fclose( pFile );
return Size;
}
/**************************************************************************************/
Section::Section(string name)
{
secName = name;
}
void Section::addOption(string key, string value)
{
this->key.push_back(key);
this->value.push_back(value);
}
string Section::getSectionName()
{
return secName;
}
void Section::removeOption(string key)
{
int pos = find(this->key.begin(), this->key.end(), key) - this->key.begin() - 1;
std::vector<string>::iterator i = this->key.begin() + pos;
this->key.erase(i);
i = this->value.begin() + pos;
this->value.erase(i);
}
std::vector<string> Section::getOptions()
{
return this->key;
}
string Section::getValue(string option)
{
bool found = false;
int i;
for (i = 0; i < this->key.size() && !found; i++)
{
if (strcmp(this->key[i].c_str(), option.c_str()) == 0)
{
found = true;
}
}
if (found)
return this->value[i - 1];
else
return NULL;
}
void Section::display()
{
std::vector<string>::iterator ik = this->key.begin();
std::vector<string>::iterator iv = this->value.begin();
for (; ik != this->key.end(); ik++)
{
cout << *ik << " = " << *iv << endl;
iv++;
}
}
bool Section::exists(string option)
{
for (int i = 0; i < this->key.size(); i++)
{
if (strcmp(this->key[i].c_str(), option.c_str()) == 0)
return true;
cout << this->key[i] << " ===== " << option << endl;
}
return false;
}
string Section::fix(string str)
{
return "";
}
Okay, TBH I've been putting this post off since you've posted it due to its length.
So I got bored about 1/4 through it, but I got the idea.
Are you trying to handle EVERYTHING, or just the basic
[header]
something="string"
something_else=number
If it's just the latter, I'd recommend (and btw, instead of char arrays, use strings, this is C++ (or at least that's what people keep telling me when I use char arrays O.o)) simply tokenizing on the equals sign, trimming trailing/leading white space, and dump the thing into a map like you're doing.
I'm pretty sure you're over-complicating the hell out of this.
I think the problem may lie in the fact that you have 15,000 functions and everything calls everything, that's a lot of parsing for each line. I'm pretty sure you need to refactor a bit, decide how much of the INI std you're going to follow, and implement it in C if you're constantly parsing 2MB + ini files..
Does your OS not provide any way of reading ini files? Also, are you against using a pre-written library. A simple google search will show many classes people have written to read ini files.
No need to reinvent the wheel.
Typing "C++ ini parser" into Google got me several libraries in the first five results. You'd have to check licensing restrictions I guess.
Maps in C++ are called "maps". Typing "C++ map" into Google got me 9.55 million results, of which I did not read them all.
As carrotcake1029 and tabstop have stated, this is more or less a solved problem, especially if you are willing to look outside of the standard library. If you have access to Boost, you could use Boost.ProgramOptions with the configuration file parser.Quote:
Originally Posted by codeprada