IniFile.NET is a .NET library to open, modify and save .INI files.
- Nuget Installation
- Ini object model
- Loading an existing .INI
- Creating an INI file
- Using properties
- Saving the INI content
- Global configuration
- Formatting the INI content
Install using package manager:
PM> Install-Package IniFile.NET
Install using dotnet
CLI:
> dotnet add package IniFile.NET
The primary class in this library is the IniFile.Ini
class and it maintains the structure of an .INI file as an in-memory object model, with objects for sections, properties (key-value pairs), comments and blank lines, allowing it to model the exact structure of a .INI file.
The IniFile.Ini
class is a collection of Section
objects (IList<Section>
). Each Section
is additionally a collection of Property
objects (IList<Property>
).
Both Section
and Property
objects contain a collection of minor objects, namely Comment
and BlankLine
objects, which are the comments and blank lines that appear before the respective sections and properties.
The Ini
class provides several constructor overloads to load .INI data from streams, text readers and files.
// Load INI data from a file
var ini = new Ini("Settings.ini");
The class also provides a static factory method Load
to create an Ini
object from a string.
const iniStr = File.ReadAllText("Settings.ini");
Ini ini = Ini.Load(iniStr);
All Ini
constructors and the Load
static factory method accept an optional IniLoadSettings
object to control how the .INI data is loaded and handled.
Property | Description | Default |
---|---|---|
CaseSensitive |
A bool indicating whether the section names and property key names in the INI file are case sensitive. |
false |
DetectEncoding |
A bool indicating whether the character encoding should be automatically detected when the INI file is loaded. |
false |
Encoding |
The character encoding to use when reading or writing data to the INI file. | UTF-8 |
IgnoreBlankLines |
A bool indicating whether to ignore blank lines when loading the INI file content. Useful if you just want to read from the INI file, but not make changes. |
false |
IgnoreComments |
A bool indicating whether to ignore comments when loading the INI file content. Useful if you just want to read from the INI file, but not make changes. |
false |
var loadSettings = new IniLoadSettings
{
Encoding = Encoding.Unicode,
DetectEncoding = true,
CaseSensitive = true
};
var ini = new Ini(stream, loadSettings);
Since the Ini
class is a collection of Section
objects (IList<Section>
) and each Section
object is a collection of Property
objects (IList<Property>
), so you can use regular IList<T>
mechanisms to add, remove and manage sections and properties.
So, for example, you can create an INI from scratch, using collection initializers, as shown here:
var ini = new Ini
{
new Section("Section Name")
{
new Property("Property1 Name", "A string value"),
new Property("Property2 Name", 10)
}
};
Properties are also name-value pairs, so you can also use the dictionary initializer syntax to create them. So the code above can also look like this:
var ini = new Ini
{
new Section("Section Name")
{
["Property1 Name"] = "A string value",
["Property2 Name"] = 10
}
};
Since they are just regular lists, you can use the regular methods and properties on IList<T>
to manage sections and properties:
// Get number of sections
int sectionCount = ini.Count;
// Add a new section
var section = new Section("New section");
ini.Add(section);
// foreach over the properties of a section
foreach (Property property in section)
{
// Your code goes here
}
// You can also use regular LINQ operations
// Check if there are any properties in a section
if (section.Any())
{
// Your code goes here
}
Any comments and blank lines appearing before a section or property belong to the respective Section
or Property
instance, and are stored in an Items
property.
; This comment and the following blank line
; belong to the Connections section.
[Connections]
; The blank line directly above, this comment
; and this comment belong to the SqlDb property
SqlDb = Db=Server;User=admin;Pwd=passw0rd1
Comments and blank lines are represented by the Comment
and BlankLine
classes, respectively.
The Items
property is a regular IList<>
collection, and can contain a mix of Comment
and BlankLine
instances.
// Two ways to add a comment to a section.
section.AddComment("This is a comment");
section.Items.Add(new Comment("This is a comment."));
// Adding a comment to a property.
property.Items.Add(new Comment("No need to specify the ; prefix. It is added automatically"));
// Two ways to add a blank line to a section
section.AddBlankLine();
section.Items.Add(new BlankLine());
// Find all comments for a property
IEnumerable<Comment> comments = property.Comments;
IEnumerable<Comment> comments = property.Items.OfType<Comment>();
Section
and Property
constructors also accept a range of strings to denote comments or blank lines. If the string is null
, empty or just whitespace, then it is considered a blank line, otherwise it is considered a comment. This code:
var section = new Section("SectionName", null, "This is a comment surrounded by blank lines", null);
will generate:
; This is a comment surrounded by blank lines
[SectionName]
INI properties are represented by the Property
class and are name-value pairs, where the name is a string
and the value can be a string
, bool
, any integral number type (int
, byte
, long
, ushort
, etc.), any floating-point number type (float
, double
and decimal
) and DateTime
.
// Write a double value to a property
section["Pi"] = 3.14d;
// Write a boolean value to a property
var property = new Property("SendMail", true);
section.Add(property);
// Read a string value from a property
string name = section["Name"];
// Read a decimal value from a property
decimal price = section["Price"];
When reading property values, if you use an implicitly-typed variable (using var
), then you will notice that the variable is of type PropertyValue
. This is the underlying type used by the framework to allow property values to support multiple types like string
, int
, bool
, etc. It does this by allowing implicit conversions between the PropertyValue
value and all the allowed types.
However, when using var
to declare the variable, the C# compiler will not know the actual type you intend the property value to be.
var value = section["property-name"]; // value will be of type PropertyValue
To get the value as the actual type, explicitly specify the variable type:
int value = section["property-name"]; // value will be of type int
Alternatively, you can explicitly cast the PropertyValue
value to the expected type:
var value = (int)section["property-value"]; // value will be of type int
The IniFile framework can recognize the following string values when reading boolean properties:
Boolean value | Allowed string values |
---|---|
true |
1 , t , y , on , yes , enabled , true |
false |
0 , f , n , off , no , disabled , false |
When writing boolean values, the IniFile framework will use the string values configured in the Ini.Config.Types.TrueString
and Ini.Config.Types.FalseString
to write the true
and false
values respectively to the output INI file.
By default, Ini.Config.Types.TrueString
is configured to 1
and Ini.Config.Types.FalseString
is configured to 0
. So, the following code:
section["HasDiscount"] = true;
section["ValidateParking"] = false;
will generate the following properties in the INI file:
HasDiscount = 1
ValidateParking = 0
You can assign custom strings to the Ini.Config.Types.TrueString
and Ini.Config.Types.FalseString
config properties.
Ini.Config.SetBooleanStrings("Oui", "Non");
// Or the long way
Ini.Config.Types.TrueString = "Oui";
Ini.Config.Types.FalseString = "Non";
Property values can be written as DateTime
values:
section["Today"] = DateTime.Now;
The IniFile framework uses the Ini.Config.Types.DateFormat
property to control how date values are represented as strings in the INI file. By default, this is defaulted to the system's short date format (CultureInfo.CurrentCulture.DateTimeFormat.ShortDatePattern
).
// Set date format to US style
Ini.Config.SetDateFormats(dateFormat: "M/dd/yyyy");
// Or the long way
Ini.Config.Types.DateFormat = "M/dd/yyyy";
// Reset the date format to system default
Ini.Config.SetDateFormats();
// Or the long way
Ini.Config.Types.DateFormat = CultureInfo.CurrentCulture.DateTimeFormat.ShortDatePattern;
When reading date values from a property, the framework will try to parse the property string value according to the format specified by the Ini.Config.Types.DateFormat
config value.
DateTime createdDate = section["CreatedDate"];
If the date string value in the INI file is a different format from the config, you can use the property's AsDateTime
method to explicitly specify the format:
DateTime createdDate = section["CreatedDate"].AsDateTime("yyyy/MM/dd");
Property values cannot be directly read or written as enum values.
To write an enum value to a property, use the enum's ToString
method to write a string representation of the value.
section["StartDay"] = DayOfWeek.Monday.ToString();
To read an enum value, the property provides an AsEnum<T>
method:
DayOfWeek startDay = section["StartDay"].AsEnum<DayOfWeek>();
Enum values are not case-sensitive.
The Ini
class provides several overloads to save the INI content to streams, text writers and files. All these overloads have synchronous and async versions.
// Synchronous call
ini.SaveTo(@"Setting.ini");
// Asynchronous call
await ini.SaveToAsync(stream);
Certain aspects of the IniFile framework can be configured using the static Ini.Config
property. This has properties to configure behaviors such as:
- Whether to allow hash symbols (
#
) to represent comments in addition to the default semi-colon (;
). - The default spacings for various types of INI objects such as sections, properties and comments.
- How to handle reading and writing of certain types of property values, such as booleans and date/times.
While, you can set the configuration properties manually, the Ini.Config
property also provides a fluent API to configure related sets of configurations:
Ini.Config
.AllowHashForComments(setAsDefault: true)
.SetSectionPaddingDefaults(insideLeft: 1, insideRight: 1)
.SetPropertyPaddingDefaults(left: 2)
.SetBooleanStrings(trueString: "YES", falseString: "NO")
.SetDateFormats(dateFormat: "M/dd/yy");
The Ini
class retains the exact formatting from the source .INI file content. It provides a Format
method to correctly format the contents.
By default, the Format
method resets the padding for all lines in the INI file.
var ini = new Ini(iniFilePath);
ini.Format();
ini.SaveTo(iniFilePath);
In addition, the Format
method takes an optional IniFormatOptions
parameter that can specify additional formatting options:
Option | Description | Default |
---|---|---|
EnsureBlankLinesBetweenSections |
If true, a blank line is inserted between each section. | false |
EnsureBlankLinesBetweenProperties |
If true, a blank line is inserted between each property. | false |
RemoveSuccessiveBlankLines |
If true, any successive blank lines are removed. | false |
var ini = new Ini(iniFilePath);
ini.Format(new IniFormatOptions
{
EnsureBlankLinesBetweenSections = true,
RemoveSuccessiveBlankLines = true
});
ini.SaveTo(iniFilePath);