Introduction
There are many classes in this site that allow saving and reading configuration files, some of which use XML while others use INI. This class will however help you save and read them in both formats with little to no effort.
It doesn't rely on age-old Win32 API because it can be quite slow.
The Code
This class uses data tables. There is one data table with three columns:
Every setting you create is going to be defined by these values.
The main methods are the following:
1. LoadFromFile(string file, FileType ft)
This allows you to initialize your configurator instance from a file. You can choose to either load an XML or an INI.
We load an XML using the default ReadXml
method available in the data table class.
As for the INI, the principle is simple. The Ini file is structured as follows:
[Section name]
Key1 name = key1 value
Key2 name = key2value
...
We go through the following sequence to read it:
- Creates a
stream
reader instance for the selected file and scans all of it - Checks if the line is at least 3 characters long
- If the line starts with a '
[
' and ends with a ']
', then the current line is a section marker:
- We split the
string
from the first to the second to last character to obtain the section name
- If the line contains an '
=
', then the line is a setting:
- We split the
string
from index 0
to the equals sign to get the key - We split it once more from the equals sign to the end to get the value
- We create a new row in the data table with the following values:
- Last encountered category name
- Current key name
- Current value
This is the code that does it:
..
while (!sr.EndOfStream)
{
string currentLine = sr.ReadLine();
if (currentLine.Length < 3) continue;
if (currentLine.StartsWith("[") &&
currentLine.EndsWith("]"))
{
currentCategory = currentLine.Substring(1, currentLine.Length - 2);
continue;
}
if (!currentLine.Contains("=")) continue;
string currentKey = currentLine.Substring(0, currentLine.IndexOf("=", StringComparison.Ordinal));
string currentValue = currentLine.Substring(currentLine.IndexOf("=", StringComparison.Ordinal) + 1);
AddValue(currentCategory, currentKey, currentValue, true);
}
..
2. AddValue(string Category, string Key, string Value, bool OverwriteExisting)
This method one allows to create a setting in the selected category with the selected name and value. What we do here is that we add a new row to the data table with the values provided.
If OverwriteExisting
is set to true
, we simply search for a match and just replace the value, if not, we just add it no matter what.
if (OverwriteExisting)
{
foreach (DataRow row in Settings.Rows.Cast<DataRow>().Where(row =>
(string) row[0] == Category && (string) row[1] == Key))
{
row[2] = Value;
return;
}
Settings.Rows.Add(Category, Key, Value);
}
else
Settings.Rows.Add(Category, Key, Value);
3. GetValue(string Category, string Key, string DefaultValue)
This function returns the value of a certain key in a certain category. However, if the key is not found, it returns DefaultValue
.
We use a loop that goes through all the rows of the table searching for a match.
4. Save(FileType ft)/Save(string filename, FileType ft)
This method saves the data table to the file specified in the LoadFromFile
method (throws an exception if it's not specified) or to a file specified in the arguments.
If the file type is XML, we use the WriteXML
method which is available in the data table class.
But if the file type is INI, the sequence is the following:
- We sort the data table by category name to group all keys of categories together
- We go through the settings one by one
- If the category of the current settings is not written yet, we mark it on the file (
[category]
) - We write the value to the file (
key=value
)
We use the following code:
StreamWriter sw = new StreamWriter(fileName);
string lastCategory ="";
foreach (DataRow row in sortedDT.Rows)
{
if ((string) row[0] != lastCategory)
{
lastCategory = (string) row[0];
sw.WriteLine("[" + lastCategory + "]");
}
sw.WriteLine((string) row[1] + "=" + (string)row[2]);
}
sw.Close();
How Do I Use It?
Using this class is quite easy. We need to create a public static
instance of the configurator
class. This will allow all of the apps to get access to the settings.
public static Configurator configurator = new Configurator();
Now we have to create all of the keys we need with their default values. This will allow all the keys to be present at all times:
...
configurator.AddValue("category1", "key1", "value1", true);
configurator.AddValue("category2", "key2", "value2", true);
...
The last thing we need to do is load settings from a file using the LoadFromFile
method. This will load all the values to the configurator
instance:
configurator.LoadFromFile("config.ini", Configurator.FileType.Ini);
OR:
configurator.LoadFromFile("config.xml", Configurator.FileType.Xml);
We're all done. Now the instance is ready to use it.
To read a value, we simply use the GetValue
method as follows:
configurator.GetValue("category", "key", "defaultvalue");
And to write a value, we use the AddValue
method:
configurator.AddValue("category", "key", "value", true);
And last but not least, we save the config using the following methods:
configurator.Save(Configurator.FileType.Ini);
OR:
configurator.Save(Configurator.FileType.Xml);
Other Uses
This class can also serve another purpose. You can convert INI to XML or the other way around.
The principle is simple: You just load the file you're going to convert and then save it to the other format.
This is how you can convert INI to XML:
Configurator config = new Configurator();
config.LoadFromFile("config.ini", Configurator.FileType.Ini);
config.Save("config.xml", Configurator.FileType.XML);
The other way around is just as simple. I'll let you experiment with it ;) !
History
- First version
- Added more details, download link available