INI Tools

Parse, validate, and convert INI configuration files

Essential for Windows applications, legacy system configurations, and simple settings files. INI (Initialization) files are one of the oldest and simplest configuration formats, still widely used in Windows applications, game configurations, and embedded systems. Our tools help you parse, convert, and work with INI files across different platforms.

What is INI?

INI (Initialization) files are simple text-based configuration files that use a basic structure of sections, properties, and values. Introduced with MS-DOS and popularized by Windows 3.x, INI files remain relevant today due to their simplicity and human readability.

History & Creation

INI files were introduced with MS-DOS in the early 1980s and became widely used with Windows 3.0 (1990). The format was designed to be simple enough to edit with basic text editors while providing structure for configuration data. Though Microsoft later promoted the Windows Registry and XML, INI files persist due to their simplicity.

Where INI is Used

  • Windows desktop applications
  • Game configuration files
  • PHP configuration (php.ini)
  • Git configuration (.gitconfig)
  • Desktop entry files (Linux .desktop)
  • Embedded systems settings
  • Legacy application configs

Benefits Over Other Formats

  • vs Registry: Portable, human-readable, easy backup, no special tools needed
  • vs XML: Much simpler syntax, smaller files, easier to edit manually
  • vs JSON: Comments supported, more forgiving syntax, simpler for basic configs
  • vs Database: No server required, plain text, version control friendly

INI Format Structure

[Sections]

Group related settings together. Section names are enclosed in square brackets.

key=value

Properties are simple key-value pairs. No quotes needed for string values.

; Comments

Comments start with semicolon (;) or hash (#). Some parsers support both.

Working with INI Files Across Systems

🪟 Windows

  • Native API support
  • Notepad for editing
  • PowerShell Get-Content
  • Many apps use INI

🐧 Linux

  • crudini tool
  • Python configparser
  • sed/awk for parsing
  • Used in .desktop files

🍎 macOS

  • No native support
  • Python configparser
  • Third-party tools
  • Less common usage

Convert INI ↔ JSON

Convert between INI and JSON formats

INI Format Examples & Best Practices

Despite its age, INI format remains popular due to its simplicity. Here are comprehensive examples showing various use cases and patterns.

Basic INI Structures

Simple Configuration File

Basic application settings with sections

; Application Configuration
[General]
AppName=My Application
Version=2.1.0
Language=en-US
Theme=dark

[Window]
Width=1280
Height=720
PositionX=100
PositionY=100
Maximized=false
Fullscreen=false

[Database]
Host=localhost
Port=5432
Database=myapp_db
Username=appuser
; Password should be stored securely, not in INI
ConnectionTimeout=30

[Logging]
Level=INFO
LogFile=app.log
MaxFileSize=10485760  ; 10MB in bytes
RotateCount=5

Game Configuration

Typical game settings file structure

; Game Settings - Last modified: 2024-01-20

[Graphics]
Resolution=1920x1080
Fullscreen=true
VSync=true
AntiAliasing=4x
TextureQuality=High
ShadowQuality=Medium
EffectsQuality=High
ViewDistance=1000
FOV=90

[Audio]
MasterVolume=80
MusicVolume=70
EffectsVolume=90
VoiceVolume=100
SpeakerMode=Stereo
EnableEAX=false

[Controls]
; Key bindings
MoveForward=W
MoveBackward=S
MoveLeft=A
MoveRight=D
Jump=Space
Crouch=Ctrl
Sprint=Shift
Interact=E
Inventory=Tab
Map=M

[Gameplay]
Difficulty=Normal
AutoSave=true
AutoSaveInterval=300  ; seconds
ShowHints=true
ShowSubtitles=true
Language=English

Advanced INI Patterns

Multi-line Values and Special Characters

Handling complex values in INI files

[Application]
; Some parsers support multi-line with backslash
Description=This is a very long description that   continues on the next line for better readability
  
; Quotes are usually not required but can be used
Path="C:Program FilesMy Appin"
AltPath=C:UsersPublicDocuments

; Special characters in values
ConnectionString=Server=localhost;Database=mydb;User Id=sa;
RegexPattern=^[a-zA-Z0-9]+@[a-zA-Z0-9]+.[a-zA-Z]{2,}$

; URL values
ApiEndpoint=https://api.example.com/v2
Webhook=https://hooks.example.com/webhook?token=abc123&type=config

; Escaped characters (parser-dependent)
Message=Line 1
Line 2	Tabbed
SpecialChars=Value with "quotes" and \backslashes\

PHP Configuration (php.ini)

Real-world example of PHP configuration

; PHP Configuration File
[PHP]
; Enable PHP short tags
short_open_tag = On

; Maximum execution time in seconds
max_execution_time = 30

; Maximum input time in seconds
max_input_time = 60

; Memory limit
memory_limit = 128M

; Error reporting
error_reporting = E_ALL & ~E_DEPRECATED & ~E_STRICT
display_errors = Off
display_startup_errors = Off
log_errors = On
error_log = /var/log/php/error.log

; File uploads
file_uploads = On
upload_max_filesize = 20M
max_file_uploads = 20

; Data handling
post_max_size = 25M
default_charset = "UTF-8"

[Date]
; Timezone setting
date.timezone = "America/New_York"

[Session]
session.save_handler = files
session.save_path = "/var/lib/php/sessions"
session.use_cookies = 1
session.cookie_httponly = 1
session.cookie_secure = 1
session.gc_maxlifetime = 1440

[opcache]
opcache.enable = 1
opcache.memory_consumption = 128
opcache.max_accelerated_files = 10000
opcache.revalidate_freq = 2

Git Configuration (.gitconfig)

Git uses INI format for configuration

[user]
    name = John Doe
    email = john.doe@example.com
    signingkey = 1234567890ABCDEF

[core]
    editor = vim
    whitespace = fix,-indent-with-non-tab,trailing-space,cr-at-eol
    excludesfile = ~/.gitignore_global
    autocrlf = input
    ignorecase = false

[color]
    ui = auto
    branch = auto
    diff = auto
    status = auto

[alias]
    st = status
    co = checkout
    br = branch
    ci = commit
    unstage = reset HEAD --
    last = log -1 HEAD
    lg = log --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset'

[push]
    default = simple
    followTags = true

[pull]
    rebase = true

[merge]
    tool = vimdiff
    conflictstyle = diff3

[diff]
    tool = vimdiff
    algorithm = patience

Desktop Entry Files (Linux)

Linux Desktop Entry (.desktop)

Application launcher configuration

[Desktop Entry]
Version=1.0
Type=Application
Name=Visual Studio Code
GenericName=Text Editor
Comment=Code Editing. Redefined.
Exec=/usr/share/code/code --unity-launch %F
Icon=visual-studio-code
Terminal=false
StartupNotify=true
StartupWMClass=Code
Categories=Development;IDE;TextEditor;
MimeType=text/plain;application/x-code-workspace;
Actions=new-empty-window;
Keywords=vscode;editor;ide;development;

[Desktop Action new-empty-window]
Name=New Empty Window
Exec=/usr/share/code/code --new-window %F
Icon=visual-studio-code

Windows Application Settings

Windows App Configuration

Typical Windows desktop application INI

; MyApp Configuration File
; Last updated: 2024-01-20

[Setup]
AppVersion=2.5.0.1234
InstallPath=C:Program FilesMyApp
DataPath=%APPDATA%MyApp
Language=1033  ; English (US)

[MainWindow]
Left=100
Top=100
Width=1024
Height=768
State=0  ; 0=Normal, 1=Minimized, 2=Maximized
AlwaysOnTop=0
Transparency=255  ; 0-255

[Preferences]
AutoUpdate=1
CheckUpdateInterval=7  ; days
ShowSplashScreen=1
SplashDuration=3000  ; milliseconds
RememberLastSession=1
ConfirmExit=1
MinimizeToTray=1

[RecentFiles]
File1=C:DocumentsProject1.dat
File2=C:DocumentsProject2.dat
File3=D:WorkAnalysis.dat
MaxRecentFiles=10

[Toolbar]
Visible=1
Position=Top
ButtonSize=Large
ShowLabels=1
CustomButtons=New,Open,Save,null,Cut,Copy,Paste,null,Help

[Plugins]
Plugin1=AdvancedTools.dll
Plugin2=DataAnalysis.dll
Plugin3=Reporting.dll
AutoLoadPlugins=1

Network Service Configuration

Service Configuration with Multiple Instances

Server configuration with environment-specific sections

; Service Configuration
[Global]
ServiceName=DataProcessor
LogLevel=INFO
MaxWorkers=10
Timeout=300

[Server:Production]
Host=prod.example.com
Port=8080
SSL=true
CertFile=/etc/ssl/certs/prod.crt
KeyFile=/etc/ssl/private/prod.key
MaxConnections=1000

[Server:Staging]
Host=staging.example.com
Port=8080
SSL=true
CertFile=/etc/ssl/certs/staging.crt
KeyFile=/etc/ssl/private/staging.key
MaxConnections=100

[Server:Development]
Host=localhost
Port=8080
SSL=false
MaxConnections=10
DebugMode=true

[Database:Production]
Driver=postgresql
Host=db-prod.example.com
Port=5432
Name=app_production
User=app_user
PoolSize=50

[Database:Development]
Driver=sqlite
Path=./dev.db
PoolSize=5

[Cache]
Enabled=true
Driver=redis
Host=cache.example.com
Port=6379
TTL=3600
MaxEntries=10000

Best Practices and Limitations

INI Format Best Practices

  • Use clear, descriptive section names
  • Keep keys consistent (use camelCase or snake_case, not both)
  • Add comments to explain non-obvious settings
  • Group related settings in sections
  • Use meaningful default values
  • Document units for numeric values (seconds, bytes, etc.)
  • Never store passwords or sensitive data in INI files

INI Format Limitations

  • No standard specification: Different parsers behave differently
  • No nested sections: Can't represent complex hierarchies
  • Limited data types: Everything is a string by default
  • No arrays: Must use workarounds like numbered keys
  • Encoding issues: Not all parsers handle Unicode well
  • Size limitations: Some Windows APIs limit INI files to 64KB

Working with INI in Different Languages

Python - ConfigParser

Reading and writing INI files in Python

import configparser
import os

# Create a config object
config = configparser.ConfigParser()

# Read INI file
config.read('app.ini')

# Access values
app_name = config['General']['AppName']
width = config.getint('Window', 'Width')
is_fullscreen = config.getboolean('Window', 'Fullscreen')

# Get with fallback
theme = config.get('General', 'Theme', fallback='light')

# Check if section/option exists
if config.has_section('Database'):
    db_host = config['Database']['Host']

# Modify values
config['Window']['Width'] = '1920'
config['Window']['Height'] = '1080'

# Add new section
config.add_section('NewFeature')
config['NewFeature']['Enabled'] = 'true'
config['NewFeature']['Level'] = '5'

# Write to file
with open('app_modified.ini', 'w') as configfile:
    config.write(configfile)

# Interpolation example
config_interp = configparser.ConfigParser(
    defaults={'home': os.path.expanduser('~')}
)
config_interp.read_string("""
[Paths]
user_dir = %(home)s/Documents
app_dir = %(home)s/MyApp
log_file = %(app_dir)s/app.log
""")

print(config_interp['Paths']['log_file'])
# Output: /home/user/MyApp/app.log

C# - Reading INI Files

Windows API and custom INI handling in C#

using System;
using System.Runtime.InteropServices;
using System.Text;
using System.Collections.Generic;

public class IniFile
{
    private string filePath;

    [DllImport("kernel32")]
    private static extern int GetPrivateProfileString(
        string section,
        string key,
        string def,
        StringBuilder retVal,
        int size,
        string filePath);

    [DllImport("kernel32")]
    private static extern long WritePrivateProfileString(
        string section,
        string key,
        string val,
        string filePath);

    public IniFile(string filePath)
    {
        this.filePath = filePath;
    }

    public string Read(string section, string key, string defaultValue = "")
    {
        var retVal = new StringBuilder(255);
        GetPrivateProfileString(section, key, defaultValue, retVal, 255, filePath);
        return retVal.ToString();
    }

    public void Write(string section, string key, string value)
    {
        WritePrivateProfileString(section, key, value, filePath);
    }

    // Helper methods
    public int ReadInt(string section, string key, int defaultValue = 0)
    {
        string value = Read(section, key, defaultValue.ToString());
        return int.TryParse(value, out int result) ? result : defaultValue;
    }

    public bool ReadBool(string section, string key, bool defaultValue = false)
    {
        string value = Read(section, key, defaultValue.ToString());
        return value.ToLower() == "true" || value == "1" || value.ToLower() == "yes";
    }
}

// Usage
var ini = new IniFile(@"C:MyAppconfig.ini");

// Read values
string appName = ini.Read("General", "AppName", "DefaultApp");
int windowWidth = ini.ReadInt("Window", "Width", 800);
bool isFullscreen = ini.ReadBool("Window", "Fullscreen", false);

// Write values
ini.Write("General", "LastRun", DateTime.Now.ToString());
ini.Write("Window", "Width", "1920");

JavaScript/Node.js - Working with INI

Parsing and generating INI files in Node.js

const fs = require('fs');
const ini = require('ini');

// Read and parse INI file
const config = ini.parse(fs.readFileSync('./config.ini', 'utf-8'));

// Access values
console.log(config.General.AppName);
console.log(config.Window.Width);

// Modify configuration
config.Window.Width = 1920;
config.Window.Height = 1080;

// Add new section
config.NewSection = {
  enabled: true,
  timeout: 30,
  retries: 3
};

// Convert back to INI format
const iniContent = ini.stringify(config, { 
  section: 'General',  // Default section for top-level keys
  whitespace: true     // Add spacing around =
});

// Write to file
fs.writeFileSync('./config_modified.ini', iniContent);

// Custom INI parser for special cases
class SimpleIniParser {
  static parse(content) {
    const lines = content.split(/
?
/);
    const result = {};
    let currentSection = null;

    for (const line of lines) {
      // Skip empty lines and comments
      if (!line.trim() || line.trim().startsWith(';') || line.trim().startsWith('#')) {
        continue;
      }

      // Section header
      const sectionMatch = line.match(/^[([^]]+)]/);
      if (sectionMatch) {
        currentSection = sectionMatch[1];
        result[currentSection] = result[currentSection] || {};
        continue;
      }

      // Key-value pair
      const keyValueMatch = line.match(/^([^=]+)=(.*)/);
      if (keyValueMatch && currentSection) {
        const key = keyValueMatch[1].trim();
        const value = keyValueMatch[2].trim();
        result[currentSection][key] = value;
      }
    }

    return result;
  }
}

// Usage of custom parser
const customConfig = SimpleIniParser.parse(fs.readFileSync('./app.ini', 'utf-8'));

Migration Strategies

When to Migrate from INI

Stay with INI when:
  • Simple key-value configuration
  • Windows desktop applications
  • Legacy system compatibility
  • User-editable settings needed
  • Minimal dependencies preferred
Consider migration when:
  • Need nested data structures
  • Require data validation
  • Want type safety
  • Need array/list support
  • Cross-platform compatibility crucial