Configuration Files

Vaibhav • September 10, 2025

As your applications grow beyond simple console programs, they often need to remember settings - things like file paths, user preferences, API keys, or feature flags. Hardcoding these values directly into your code is brittle and inflexible. Instead, we use configuration files - external files that store settings in a structured format. In this article, we’ll explore how to work with configuration files in C#, including reading and writing INI, JSON, and XML formats using only the concepts we’ve covered so far.

Why Use Configuration Files?

Configuration files allow your application to be customized without recompiling. For example, you might want to change the logging level, switch between test and production databases, or enable/disable features - all without touching the source code.

Benefits include:

  • Separation of code and configuration
  • Easy updates and environment-specific settings
  • Support for automation and deployment

C# supports multiple configuration formats, but we’ll focus on three common ones: INI, JSON, and XML.

INI Files - Simple Key-Value Settings

INI files are one of the oldest configuration formats. They’re simple, human-readable, and organized into sections. Here’s an example:

[AppSettings]
Theme=Dark
MaxUsers=100
EnableLogging=true

Each section is marked by square brackets, and each setting is a key-value pair. While .NET doesn’t have built-in support for INI files, you can parse them manually using StreamReader and string operations.

Dictionary<string, string> settings = new();

foreach (string line in File.ReadLines("config.ini"))
{
    if (string.IsNullOrWhiteSpace(line) || line.StartsWith("["))
        continue;

    string[] parts = line.Split('=');
    if (parts.Length == 2)
    {
        settings[parts[0].Trim()] = parts[1].Trim();
    }
}

Console.WriteLine($"Theme: {settings["Theme"]}");

This reads each line, skips empty lines and section headers, splits key-value pairs, and stores them in a dictionary. You can then access settings by key.

Writing INI Files

Writing an INI file is just writing plain text. You can use StreamWriter to output the structure:

using StreamWriter writer = new StreamWriter("config.ini");

writer.WriteLine("[AppSettings]");
writer.WriteLine("Theme=Light");
writer.WriteLine("MaxUsers=50");
writer.WriteLine("EnableLogging=false");

This creates a new INI file with updated settings. You can also write comments using ; or #.

JSON Files - Structured and Modern

JSON (JavaScript Object Notation) is the most popular format for configuration today. It’s structured, supports nested objects, and is widely used in web APIs and cloud services. Here’s a sample:

{
  "AppSettings": {
    "Theme": "Dark",
    "MaxUsers": 100,
    "EnableLogging": true
  }
}

To read JSON in C#, you can use the built-in System.Text.Json namespace. Let’s define a class to match the structure:

public class AppSettings
{
    public string Theme { get; set; }
    public int MaxUsers { get; set; }
    public bool EnableLogging { get; set; }
}

public class Config
{
    public AppSettings AppSettings { get; set; }
}

Now read the file and deserialize it:

using System.Text.Json;

string json = File.ReadAllText("config.json");
Config config = JsonSerializer.Deserialize<Config>(json);

Console.WriteLine($"Theme: {config.AppSettings.Theme}");

This loads the JSON file, maps it to your class structure, and gives you typed access to settings. It’s clean, safe, and easy to extend.

Writing JSON Files

You can also serialize objects back to JSON using JsonSerializer:

Config config = new Config
{
    AppSettings = new AppSettings
    {
        Theme = "Light",
        MaxUsers = 50,
        EnableLogging = false
    }
};

string json = JsonSerializer.Serialize(config, new JsonSerializerOptions { WriteIndented = true });
File.WriteAllText("config.json", json);

This creates a nicely formatted JSON file. The WriteIndented option makes it human-readable.

XML Files - Verbose but Powerful

XML (eXtensible Markup Language) is another structured format, used heavily in older .NET applications and enterprise systems. Here’s an example:

<AppSettings>
  <Theme>Dark</Theme>
  <MaxUsers>100</MaxUsers>
  <EnableLogging>true</EnableLogging>
</AppSettings>

You can read XML using XmlDocument or XDocument. Let’s use XmlDocument for simplicity:

using System.Xml;

XmlDocument doc = new XmlDocument();
doc.Load("config.xml");

string theme = doc.SelectSingleNode("/AppSettings/Theme").InnerText;
int maxUsers = int.Parse(doc.SelectSingleNode("/AppSettings/MaxUsers").InnerText);
bool enableLogging = bool.Parse(doc.SelectSingleNode("/AppSettings/EnableLogging").InnerText);

Console.WriteLine($"Theme: {theme}");

This reads values using XPath expressions. You can also navigate nodes manually or use LINQ to XML for more advanced scenarios.

Writing XML Files

To write XML, use XmlWriter or build a string manually. Here’s a basic example:

using XmlWriter writer = XmlWriter.Create("config.xml");

writer.WriteStartDocument();
writer.WriteStartElement("AppSettings");

writer.WriteElementString("Theme", "Light");
writer.WriteElementString("MaxUsers", "50");
writer.WriteElementString("EnableLogging", "false");

writer.WriteEndElement();
writer.WriteEndDocument();

This creates a well-formed XML file with the desired settings. You can also add attributes, comments, and namespaces if needed.

Choosing the Right Format

Each format has its strengths:

  • INI - simple, lightweight, good for small apps
  • JSON - modern, structured, ideal for web and cloud
  • XML - verbose, but powerful for enterprise and legacy systems

For most new applications, JSON is the preferred choice due to its balance of readability and structure.

Best Practices for Configuration Files

Configuration files are critical to your app’s behavior. Treat them with care:

  • Keep them outside your source code (e.g., in a config folder)
  • Use version control to track changes
  • Validate values before using them
  • Use environment-specific configs (e.g., appsettings.Development.json)
  • Never store secrets (like passwords or API keys) in plain text

Use a layered configuration approach - default settings in code, overridden by config files, and finally by environment variables. This gives flexibility and security.

Real-World Use Case: Theme Switcher

Let’s build a simple app that reads a theme setting from a JSON file and applies it:

public class AppSettings
{
    public string Theme { get; set; }
}

string json = File.ReadAllText("config.json");
AppSettings settings = JsonSerializer.Deserialize<AppSettings>(json);

if (settings.Theme == "Dark")
{
    Console.BackgroundColor = ConsoleColor.Black;
    Console.ForegroundColor = ConsoleColor.White;
}
else
{
    Console.BackgroundColor = ConsoleColor.White;
    Console.ForegroundColor = ConsoleColor.Black;
}

Console.Clear();
Console.WriteLine($"Theme applied: {settings.Theme}");

This reads the theme from config and updates the console colors accordingly. You can extend this to support more settings or UI themes.

Summary

Configuration files are a vital part of building flexible, maintainable applications. In this article, you learned how to read and write INI, JSON, and XML files using basic C# techniques. You explored how to parse key-value pairs, deserialize structured data, and build real-world workflows like theme switching and backups. These skills will help you build apps that adapt to different environments, users, and requirements - all without changing your code. In the next chapter, we’ll dive into generics and type safety - unlocking the power of reusable, strongly typed components.