Introduction
Originally, this started out as a C++ class (CIniFile) in 2005. Since then, I rewrote CIniFile
so it would be more efficient. The following code is a C#\VB.NET\VBScript port of the C++ code. Almost all the class names are the same. with the exception to the leading "C" which has been dropped. The current class names are IniFile
, IniSection
, and IniKey
.
To help with understanding how to use the code, usage in the following languages will be demonstrated:
The following source versions of the Inifile
object are provided:
- C# - InifileCs.cs
- VB.NET - InifileVb.vb
- VBScript - IniFile.vbs
Efficiency
During testing on Windows7 running on a Lenovo T60 w\2GB RAM, IniFile
could generate an ini file holding 10000 sections with 100 keys per section and write it to disk in ~2 second(s). After increasing the keys per section to 1000, the file was generated in ~6 seconds. The file was 10,000,000 lines long, and was roughly 140MB in size. Reading the data back from the file into memory was in the same ball park.
[Section0]
Key0=KeyValue
Key1=KeyValue
Key2=KeyValue
...
[Section1]
Key0=KeyValue
Key1=KeyValue
Key2=KeyValue
...
Parsing and Behavior
Currently, IniFile
is designed to read most ini files. Ini sections should start with a "[" and end with a "]". Whitespace between "[" and "]" will be trimmed. For example, the section defined below would be interpreted as "SECTION
", not " SECTION
".
[ SECTION ]
...
...
...
Ini key\value pairs should have a key value separated by an "=" to the right of the key value. Key values are also trimmed to remove whitespace. For example, the key defined below would be interpreted as "MyKeyValue=SomeData
". The resulting key would be "MyKeyValue
" and value would be "SomeData
".
[ SECTION ]
MyKeyValue =SomeData
...
...
Ini key values, however, are not trimmed, and whitespace is preserved. For example, the key defined below would be interpreted as "MyIniKey= SomeDataWithSpaces
". The resulting key would be "MyKeyValue
", and value would be " SomeDataWithSpaces
".
[ SECTION ]
MyKeyValue = SomeDataWithSpaces
...
...
Functions and Returns
public class IniFile
{
public IniFile()
public void Load(string sFileName )
public void Load(string sFileName, bool bMerge )
public void Save(string sFileName)
public System.Collections.ICollection Sections
public IniSection AddSection(string sSection )
public bool RemoveSection(string sSection)
public bool RemoveSection(IniSection Section)
public bool RemoveAllSections()
public IniSection GetSection(string sSection)
public string GetKeyValue(string sSection, string sKey)
public bool SetKeyValue(string sSection, string sKey, string sValue)
public bool RenameSection(string sSection, string sNewSection)
public bool RenameKey(string sSection, string sKey, string sNewKey)
public class IniSection
{
protected internal IniSection(IniFile parent, string sSection)
public System.Collections.ICollection Keys
public string Name
public IniKey AddKey(string sKey)
public bool RemoveKey(string sKey)
public bool RemoveKey(IniKey Key)
public bool RemoveAllKeys()
public IniKey GetKey(string sKey)
public bool SetName(string sSection)
public string GetName()
public class IniKey
{
protected internal IniKey(IniSection parent, string sKey)
public string Name
public string Value
public void SetValue(string sValue)
public string GetValue()
public bool SetName(string sKey)
public string GetName()
}
}
}
Using IniFile.Sections and IniSection.Keys
The following code will demonstrate how to use the Sections
and Keys
properties:
IniFile ini = new IniFile();
ini.Load("C:\\temp\\test.ini");
foreach (IniSection s in ini.Sections)
{
Trace.WriteLine(string.Format("Section: [{0}]", s.Name));
foreach (IniSection.IniKey k in s.Keys)
{
if (k.Value != string.Empty)
{
Trace.WriteLine(string.Format("Key: {0}={1}", k.Name, k.Value));
}
else
{
Trace.WriteLine(string.Format("Key: {0}", k.Name));
}
}
}
Merging INI files
The following code demonstrates merging two ini files:
IniFile ini = new IniFile();
ini.Load("C:\\temp\\test1.ini");
ini.Load("C:\\temp\\test2.ini" , true );
ini.Save("C:\\temp\\test1and2.ini" );
Using IniFile in C#
This code demonstrates the usage in C#:
static void Main(string[] args)
{
IniFile ini = new IniFile();
ini.AddSection("TEST_SECTION").AddKey("Key1").Value = "Value1";
ini.AddSection("TEST_SECTION").AddKey("Key2").Value = "Value2";
ini.AddSection("TEST_SECTION").AddKey("Key3").Value = "Value3";
ini.AddSection("TEST_SECTION").AddKey("Key4").Value = "Value4";
ini.AddSection("TEST_SECTION").AddKey("Key5").Value = "Value5";
ini.AddSection("TEST_SECTION").AddKey("Key6").Value = "Value6";
ini.AddSection("TEST_SECTION").AddKey("Key7").Value = "Value7";
ini.AddSection("TEST_SECTION_2").AddKey("Key1").Value = "Value1";
ini.AddSection("TEST_SECTION_2").AddKey("Key2").Value = "Value2";
ini.AddSection("TEST_SECTION_2").AddKey("Key3").Value = "Value3";
ini.AddSection("TEST_SECTION_2").AddKey("Key4").Value = "Value4";
ini.AddSection("TEST_SECTION_2").AddKey("Key5").Value = "Value5";
ini.AddSection("TEST_SECTION_2").AddKey("Key6").Value = "Value6";
ini.AddSection("TEST_SECTION_2").AddKey("Key7").Value = "Value7";
Trace.Write("Key Rename Key1 -> KeyTemp Test: ");
if (ini.RenameKey("TEST_SECTION", "Key1", "KeyTemp"))
Trace.WriteLine("Pass");
else
Trace.WriteLine("Fail");
Trace.Write("Test section rename TEST_SECTION -> TEST_SECTION_3: ");
if (ini.RenameSection("TEST_SECTION", "TEST_SECTION_3"))
Trace.WriteLine("Pass");
else
Trace.WriteLine("Fail");
Trace.Write("Test TEST_SECTION_3 rename key KeyTemp -> Key1: ");
if (ini.RenameKey("TEST_SECTION_3", "KeyTemp", "Key1"))
Trace.WriteLine("Pass");
else
Trace.WriteLine("Fail");
Trace.Write("Test section rename TEST_SECTION_3 -> TEST_SECTION: ");
if (ini.RenameSection("TEST_SECTION_3", "TEST_SECTION"))
Trace.WriteLine("Pass");
else
Trace.WriteLine("Fail");
Trace.Write("Test TEST_SECTION key rename Key1 -> Key2 where Key2 exists: ");
if (ini.RenameKey("TEST_SECTION", "Key2", "Key1"))
Trace.WriteLine("Pass");
else
Trace.WriteLine("Fail");
Trace.Write("Test TEST_SECTION key rename Key2 -> Key2Renamed: ");
if (ini.RenameKey("TEST_SECTION", "Key2", "Key2Renamed"))
Trace.WriteLine("Pass");
else
Trace.WriteLine("Fail");
Trace.Write("Test section rename TEST_SECTION_2 -> TEST_SECTION_1 : ");
if (ini.RenameSection("TEST_SECTION_2", "TEST_SECTION_1"))
Trace.WriteLine("Pass");
else
Trace.WriteLine("Fail");
Trace.Write("Test TEST_SECTION_1 remove key Key1: ");
if (ini.GetSection("TEST_SECTION_1").RemoveKey("Key1"))
Trace.WriteLine("Pass");
else
Trace.WriteLine("Fail");
Trace.Write("Test TEST_SECTION_1 remove key Key1: ");
if (ini.GetSection("TEST_SECTION_1").RemoveKey("Key1"))
Trace.WriteLine("Pass");
else
Trace.WriteLine("Fail");
Trace.Write("Test remove section TEST_SECTION_1: ");
if (ini.RemoveSection("TEST_SECTION_1"))
Trace.WriteLine("Pass");
else
Trace.WriteLine("Fail");
Trace.Write("Test remove section TEST_SECTION_1: ");
if (ini.RemoveSection("TEST_SECTION_1"))
Trace.WriteLine("Pass");
else
Trace.WriteLine("Fail");
ini.Save("C:\\temp\\test.ini");
}
Using IniFile in VB.NET
This code demonstrates the usage in VB.NET:
Sub Main()
Dim ini As New IniFile
ini.AddSection("TEST_SECTION").AddKey("Key1").Value = "Value1"
ini.AddSection("TEST_SECTION").AddKey("Key2").Value = "Value2"
ini.AddSection("TEST_SECTION").AddKey("Key3").Value = "Value3"
ini.AddSection("TEST_SECTION").AddKey("Key4").Value = "Value4"
ini.AddSection("TEST_SECTION").AddKey("Key5").Value = "Value5"
ini.AddSection("TEST_SECTION").AddKey("Key6").Value = "Value6"
ini.AddSection("TEST_SECTION").AddKey("Key7").Value = "Value7"
ini.AddSection("TEST_SECTION_2").AddKey("Key1").Value = "Value1"
ini.AddSection("TEST_SECTION_2").AddKey("Key2").Value = "Value2"
ini.AddSection("TEST_SECTION_2").AddKey("Key3").Value = "Value3"
ini.AddSection("TEST_SECTION_2").AddKey("Key4").Value = "Value4"
ini.AddSection("TEST_SECTION_2").AddKey("Key5").Value = "Value5"
ini.AddSection("TEST_SECTION_2").AddKey("Key6").Value = "Value6"
ini.AddSection("TEST_SECTION_2").AddKey("Key7").Value = "Value7"
Trace.Write("Key Rename Key1 -> KeyTemp Test: ")
If ini.RenameKey("TEST_SECTION", "Key1", "KeyTemp") Then
Trace.WriteLine("Pass") Else Trace.WriteLine("Fail")
Trace.Write("Test section rename TEST_SECTION -> TEST_SECTION_3: ")
If ini.RenameSection("TEST_SECTION", "TEST_SECTION_3") Then
Trace.WriteLine("Pass") Else Trace.WriteLine("Fail")
Trace.Write("Test TEST_SECTION_3 rename key KeyTemp -> Key1: ")
If ini.RenameKey("TEST_SECTION_3", "KeyTemp", "Key1") Then
Trace.WriteLine("Pass") Else Trace.WriteLine("Fail")
Trace.Write("Test section rename TEST_SECTION_3 -> TEST_SECTION: ")
If ini.RenameSection("TEST_SECTION_3", "TEST_SECTION") Then
Trace.WriteLine("Pass") Else Trace.WriteLine("Fail")
Trace.Write("Test TEST_SECTION key rename Key1 -> Key2 where Key2 exists: ")
If ini.RenameKey("TEST_SECTION", "Key2", "Key1") Then
Trace.WriteLine("Pass") Else Trace.WriteLine("Fail")
Trace.Write("Test TEST_SECTION key rename Key2 -> Key2Renamed: ")
If ini.RenameKey("TEST_SECTION", "Key2", "Key2Renamed") Then
Trace.WriteLine("Pass") Else Trace.WriteLine("Fail")
Trace.Write("Test section rename TEST_SECTION_2 -> TEST_SECTION_1 : ")
If ini.RenameSection("TEST_SECTION_2", "TEST_SECTION_1") Then
Trace.WriteLine("Pass") Else Trace.WriteLine("Fail")
Trace.Write("Test TEST_SECTION_1 remove key Key1: ")
If ini.GetSection("TEST_SECTION_1").RemoveKey("Key1") Then
Trace.WriteLine("Pass") Else Trace.WriteLine("Fail")
Trace.Write("Test TEST_SECTION_1 remove key Key1: ")
If ini.GetSection("TEST_SECTION_1").RemoveKey("Key1") Then
Trace.WriteLine("Pass") Else Trace.WriteLine("Fail")
Trace.Write("Test remove section TEST_SECTION_1: ")
If ini.RemoveSection("TEST_SECTION_1") Then
Trace.WriteLine("Pass") Else Trace.WriteLine("Fail")
Trace.Write("Test remove section TEST_SECTION_1: ")
If ini.RemoveSection("TEST_SECTION_1") Then
Trace.WriteLine("Pass") Else Trace.WriteLine("Fail")
ini.Save("C:\temp\test.ini")
End Sub
Using IniFile in VBScript
This code demonstrates the usage in VBScript:
Option Explicit
Call Main
Sub Main()
Dim ini
Set ini = New IniFile
ini.AddSection("TEST_SECTION").AddKey("Key1").Value = "Value1"
ini.AddSection("TEST_SECTION").AddKey("Key2").Value = "Value2"
ini.AddSection("TEST_SECTION").AddKey("Key3").Value = "Value3"
ini.AddSection("TEST_SECTION").AddKey("Key4").Value = "Value4"
ini.AddSection("TEST_SECTION").AddKey("Key5").Value = "Value5"
ini.AddSection("TEST_SECTION").AddKey("Key6").Value = "Value6"
ini.AddSection("TEST_SECTION").AddKey("Key7").Value = "Value7"
ini.AddSection("TEST_SECTION_2").AddKey("Key1").Value = "Value1"
ini.AddSection("TEST_SECTION_2").AddKey("Key2").Value = "Value2"
ini.AddSection("TEST_SECTION_2").AddKey("Key3").Value = "Value3"
ini.AddSection("TEST_SECTION_2").AddKey("Key4").Value = "Value4"
ini.AddSection("TEST_SECTION_2").AddKey("Key5").Value = "Value5"
ini.AddSection("TEST_SECTION_2").AddKey("Key6").Value = "Value6"
ini.AddSection("TEST_SECTION_2").AddKey("Key7").Value = "Value7"
If ini.RenameKey("TEST_SECTION","Key1","KeyTemp") Then
WScript.Echo "Pass" Else WScript.Echo "Fail"
If ini.RenameSection("TEST_SECTION","TEST_SECTION_3") Then
WScript.Echo "Pass" Else WScript.Echo "Fail"
If ini.RenameKey("TEST_SECTION_3","KeyTemp","Key1") Then
WScript.Echo "Pass" Else WScript.Echo "Fail"
If ini.RenameSection("TEST_SECTION_3","TEST_SECTION") Then
WScript.Echo "Pass" Else WScript.Echo "Fail"
If ini.RenameKey("TEST_SECTION","Key2","Key1") Then
WScript.Echo "Pass" Else WScript.Echo "Fail"
If ini.RenameKey("TEST_SECTION","Key2","Key2Renamed") Then
WScript.Echo "Pass" Else WScript.Echo "Fail"
If ini.RenameSection("TEST_SECTION_2","TEST_SECTION_1") Then
WScript.Echo "Pass" Else WScript.Echo "Fail"
If ini.GetSection("TEST_SECTION_1").RemoveKey("Key1") Then
WScript.Echo "Pass" Else WScript.Echo "Fail"
If ini.GetSection("TEST_SECTION_1").RemoveKey("Key1") Then
WScript.Echo "Pass" Else WScript.Echo "Fail"
If ini.RemoveSection("TEST_SECTION_1") Then
WScript.Echo "Pass" Else WScript.Echo "Fail"
If ini.RemoveSection("TEST_SECTION_1") Then
WScript.Echo "Pass" Else WScript.Echo "Fail"
ini.Save("C:\temp\test.ini")
End Sub
Using the lib in .NET
In order to use the IniFile
library, it is necessary to add a reference to IniFile.dll.
History
- 12\14\2007 - Created - Initial VBScript version
- 12\08\2007 - Bug fixed - Regex parse string issue
- 08\23\2010 - Created - C# version which uses hashing
- 08\23\2010 - Created - VB.NET version which uses hashing
- 08\23\2010 - Created - VBScript version which uses hashing
- 11\12\2010 - Bug fixed - Section regex matching on key values with brackets
- 06\20\2015 - Bug fixed - Key parsing regex to account for keys with spaces in names
- 11\13\2015 - Bug fixed - Key parsing regex to account for keys with multiple equals
- 05\06\2021 - Bug fixed- Section regex to read everything within brakets and trim (single char issue)