Skip to content

Instantly share code, notes, and snippets.

@DreamVB
Last active September 25, 2021 20:39
Show Gist options
  • Save DreamVB/fe5c7273da10c59273b0a0a0f02cf2d0 to your computer and use it in GitHub Desktop.
Save DreamVB/fe5c7273da10c59273b0a0a0f02cf2d0 to your computer and use it in GitHub Desktop.
A full INI reader and writer for C#
// DreamVB.Config Version 1.0.1
// This is a full class for reading and writing to Windows INI Files.
// This project is a raw class uses no Windows API class.
// What's in side this class
// Load config data from a file.
// Load config data from a raw string
// Read and write string values
// Read and write Integer, Double values, Boolean values, Long values
// Read strings that have line breaks and also write strings with line breaks.
// Read and Write binary data to the config file
// Return a collection of selections
// Return a collection of keys form a selection passed.
// Delete selections and all the values and keys
// Check if a selection exists
// Check if a key exists in a selection
// Delete a key and a value
// Save to other filenames
// Update the current loaded config file
// Hope you find this class useful.
// By DreamVB email [email protected]
using System;
using System.Security;
using System.Collections.Generic;
using System.Collections;
using System.IO;
using System.Windows.Forms;
namespace DreamVB.Config
{
public class cfgfile
{
private string m_config_file = string.Empty;
private struct TSelction_Pair
{
public string Name;
public string Key;
}
private Hashtable ht = null;
/// <summary>
/// Constructor to load config file data, Data can be passed as a filename or a string
/// When ReadFromFile is set to false data is assumed to be read from a string
/// </summary>
/// <param name="source"></param>
/// <param name="ReadFromFile"></param>
public cfgfile(string source, bool ReadFromFile = true)
{
ht = new Hashtable();
//Read config data from file
if (ReadFromFile)
{
m_config_file = source;
//Make hash table
ParseFileConfig(m_config_file);
}
else
{
//Read config data from string.
ParseStringConfig(source);
}
}
public cfgfile()
{
ht = new Hashtable();
}
private string FixKeyName(string KeyName)
{
//Uppercase the first letter and lowercase the rest
return char.ToUpper(KeyName[0]).ToString() + KeyName.Substring(1).ToLower();
}
/// <summary>
/// Loads an config file data from a string
/// </summary>
/// <param name="data"></param>
private void ParseStringConfig(string data)
{
StringReader sr;
string s_line = null;
string s_selection = string.Empty;
string s_key = string.Empty;
string s_val = string.Empty;
TSelction_Pair pair;
int s_pos=-1;
if (data.Length.Equals(0))
{
return;
}
try
{
sr = new StringReader(data);
//Get first line
s_line = sr.ReadLine().Trim();
while (s_line != null)
{
//Check length
if (s_line.Length.Equals(0))
{
continue;
}
//Skip comments
if (s_line[0].Equals(';'))
{
continue;
}
//Check for selection.
if (s_line.StartsWith("[") && (s_line.EndsWith("]")))
{
s_selection = s_line.Substring(1, s_line.IndexOf("]") - 1).Trim();
}
else
{
//Look for =
s_pos = s_line.IndexOf("=");
if (s_pos != -1)
{
//Extract key value name
s_key = s_line.Substring(0, s_pos).Trim().ToUpper();
//Extract the keys value
s_val = s_line.Substring(s_pos + 1).Trim();
//Set pair name to selection name
pair.Name = s_selection.ToUpper();
//Set selection pair key
pair.Key = s_key;
//Add to the hash list
ht.Add(pair, s_val);
}
}
//Fetch next line
s_line = sr.ReadLine();
}
}
catch (Exception ex)
{
throw new Exception(ex.Message);
}
//Clear up
sr.Dispose();
}
/// <summary>
/// Load the config filename
/// </summary>
/// <param name="Filename"></param>
private void ParseFileConfig(string Filename)
{
string s_line = string.Empty;
string s_selection = string.Empty;
string s_key = string.Empty;
string s_val = string.Empty;
int s_pos = (-1);
TSelction_Pair pair;
//Check if the filename exists
if (!File.Exists(Filename))
{
throw new FileNotFoundException("File Not Found:\n" + Filename);
}
try
{
using (StreamReader sr = new StreamReader(Filename))
{
//Read till end of file.
while(!sr.EndOfStream)
{
s_line = sr.ReadLine().Trim();
//Check length
if (s_line.Length.Equals(0))
{
continue;
}
//Skip comments
if (s_line[0].Equals(';'))
{
continue;
}
//Check for selection.
if (s_line.StartsWith("[") && (s_line.EndsWith("]")))
{
s_selection = s_line.Substring(1, s_line.IndexOf("]") - 1).Trim();
}
else
{
//Look for =
s_pos = s_line.IndexOf("=");
if (s_pos != -1)
{
//Extract key value name
s_key = s_line.Substring(0, s_pos).Trim().ToUpper();
//Extract the keys value
s_val = s_line.Substring(s_pos + 1).Trim();
//Set pair name to selection name
pair.Name = s_selection.ToUpper();
//Set selection pair key
pair.Key = s_key;
//Add to the hash list
ht.Add(pair,s_val);
}
}
}
//Close file
sr.Close();
}
}
catch (Exception ex)
{
throw new Exception(ex.Message);
}
}
/// <summary>
/// Update the input main config file.
/// </summary>
public void Update()
{
//Check that length of not zero
if (m_config_file.Length == 0)
{
return;
}
//Save the config file.
SaveIniFile(m_config_file);
}
/// <summary>
/// Save the config data to a new filename
/// </summary>
/// <param name="Filename"></param>
public void SaveIniFile(string Filename)
{
List<string> selections = new List<string>();
string StrLine = string.Empty;
try
{
//Open file for writing
using (StreamWriter sw = new StreamWriter(Filename))
{
foreach (TSelction_Pair pair in ht.Keys)
{
//Check if selection is in the list
if (!selections.Contains(pair.Name))
{
//Add it to the list
selections.Add(pair.Name);
}
}
foreach (string sel in selections)
{
//Line to save to file selection
StrLine += ("[" + sel + "]" + Environment.NewLine);
foreach (TSelction_Pair pair in ht.Keys)
{
//Check if pair selection name equals Selection
if (pair.Name.Equals(sel))
{
//Fetch value from hash table pair
string temp_value = (string)ht[pair];
//Check to see if the value is null
if (temp_value != null)
temp_value = "=" + temp_value;
//Proper case the key name
string sKey = FixKeyName(pair.Key);
//Append key and value to StrLine
StrLine += (sKey + temp_value + Environment.NewLine);
}
}
//Append lash new line break
StrLine += Environment.NewLine;
}
//Save StrLine to file trim the excess spaces and append a new line.
sw.Write(StrLine.TrimEnd() + Environment.NewLine);
//Close file
sw.Close();
}
}
catch (Exception ex)
{
//Raise error
throw new Exception(ex.Message);
}
}
/// <summary>
/// Return a list object of selection names
/// </summary>
public List<string> ReadSelections
{
get
{
List<string> sels = new List<string>();
foreach (TSelction_Pair pair in ht.Keys)
{
//Check if the selection name already exists in the list
if (!sels.Contains(pair.Name))
{
//Add to selections list
sels.Add(pair.Name);
}
}
return sels;
}
}
/// <summary>
/// Return true if a selection is found in the config file
/// </summary>
/// <param name="Selection"></param>
/// <returns></returns>
public bool HasSelection(string Selection)
{
bool Found = false;
foreach (TSelction_Pair pair in ht.Keys)
{
//Check if pair selection equals Selection string
if (pair.Name.Equals(Selection, StringComparison.OrdinalIgnoreCase))
{
//Set found to true
Found = true;
//Exit
break;
}
}
//Return Found value
return Found;
}
/// <summary>
/// Return true if a key is found in the config file
/// </summary>
/// <param name="Selection"></param>
/// <param name="Key"></param>
/// <returns></returns>
public bool HasKey(string Selection, string Key)
{
bool Found = false;
foreach (TSelction_Pair pair in ht.Keys)
{
//Check that we are on the correct selection
if (pair.Name.Equals(Selection, StringComparison.OrdinalIgnoreCase))
{
//Check that the key is in the selection above
if (Key.Equals(pair.Key, StringComparison.OrdinalIgnoreCase))
{
//Set found to true
Found = true;
}
}
}
return Found;
}
public List<string> ReadKeys(string Selection)
{
List<string> _keys = new List<string>();
if (Selection.Length == 0)
{
return _keys;
}
foreach (TSelction_Pair pair in ht.Keys)
{
// Check if pair selection name equals Selection string
if (pair.Name.Equals(Selection, StringComparison.OrdinalIgnoreCase))
{
//Add pair to hash table
_keys.Add(FixKeyName(pair.Key));
}
}
//Return keys
return _keys;
}
/// <summary>
/// Read a string value from a config file
/// </summary>
/// <param name="Selection"></param>
/// <param name="Key"></param>
/// <param name="vDefault"></param>
/// <returns></returns>
public string ReadString(string Selection, string Key, string vDefault = "")
{
TSelction_Pair pair;
string sVal = string.Empty;
//Set pair selection name to uppercase
pair.Name = Selection.ToUpper();
//Set pair key to uppercase
pair.Key = Key.ToUpper();
try
{
//Fetch the object from the hash table
sVal = (string)ht[pair];
//Check if sVal is empty
if (sVal.Equals(""))
{
//Return default
return vDefault;
}
else
{
return sVal;
}
}
catch
{
//Return default
return vDefault;
}
}
/// <summary>
/// Reads an integer value from the config file
/// </summary>
/// <param name="Selection"></param>
/// <param name="Key"></param>
/// <param name="vDefault"></param>
/// <returns></returns>
public int ReadInteger(string Selection, string Key, int vDefault = 0)
{
string value = ReadString(Selection, Key, vDefault.ToString());
return int.Parse(value);
}
/// <summary>
/// Reads a long value from a config file
/// </summary>
/// <param name="Selection"></param>
/// <param name="Key"></param>
/// <param name="vDefault"></param>
/// <returns></returns>
public long ReadLong(string Selection, string Key, long vDefault = 0)
{
string value = ReadString(Selection, Key, vDefault.ToString());
return long.Parse(value);
}
/// <summary>
/// Read a double value from the config file
/// </summary>
/// <param name="Selection"></param>
/// <param name="Key"></param>
/// <param name="vDefault"></param>
/// <returns></returns>
public double ReadDouble(string Selection, string Key, double vDefault = 0.0)
{
string value = ReadString(Selection, Key, vDefault.ToString());
return Double.Parse(value);
}
/// <summary>
/// Returns a bool value from a config file
/// </summary>
/// <param name="Selection"></param>
/// <param name="Key"></param>
/// <param name="vDefault"></param>
/// <returns></returns>
public bool ReadBool(string Selection, string Key, bool vDefault = false)
{
string value = ReadString(Selection, Key, vDefault.ToString()).ToLower();
bool bValue = vDefault;
//Test for true value
if (value == "true" || value == "on" || value == "yes" || value == "1")
{
bValue = true;
}
//Test for false value
else if (value == "false" || value == "off" || value == "no" || value == "0")
{
bValue = false;
}
else
{
bValue = vDefault;
}
return bValue;
}
/// <summary>
/// Write or update a bool value to a config file
/// </summary>
/// <param name="Selection"></param>
/// <param name="Key"></param>
/// <param name="Value"></param>
public void WriteBool(string Selection, string Key, bool Value)
{
WriteString(Selection, Key, Value.ToString());
}
/// <summary>
/// Write or update an existing key value in the config file
/// </summary>
/// <param name="Selection"></param>
/// <param name="Key"></param>
/// <param name="Value"></param>
public void WriteString(string Selection, string Key, string Value)
{
TSelction_Pair tmp;
tmp.Name = Selection.ToUpper().Trim();
tmp.Key = Key.ToUpper().Trim();
if (tmp.Name.Length == 0)
{
throw new Exception("Selection name required.");
}
else if (tmp.Key.Length == 0)
{
throw new Exception("Selection found key expected.");
}
else
{
//Remove the old selection and key
if (ht.Contains(tmp))
{
ht.Remove(tmp);
}
//Add new obj
ht.Add(tmp, Value);
}
}
/// <summary>
/// Write or update a string with line new line breaks
/// </summary>
/// <param name="Selection"></param>
/// <param name="Key"></param>
/// <param name="Value"></param>
public void WriteMultilineString(string Selection, string Key, string Value)
{
WriteString(Selection, Key, Value.Replace(Environment.NewLine, "\\n"));
}
/// <summary>
/// Read in a string value with new line breaks
/// </summary>
/// <param name="Selection"></param>
/// <param name="Key"></param>
/// <param name="vDefault"></param>
/// <returns></returns>
public string ReadMultilineString(string Selection, String Key, String vDefault = "")
{
return ReadString(Selection, Key, vDefault).Replace("\\n", Environment.NewLine);
}
/// <summary>
/// Write or update an existing integer value in the config file
/// </summary>
/// <param name="Selection"></param>
/// <param name="Key"></param>
/// <param name="Value"></param>
public void WriteInteger(string Selection, string Key, int Value)
{
WriteString(Selection, Key, Value.ToString());
}
/// <summary>
/// Write or update an existing long value in the config file
/// </summary>
/// <param name="Selection"></param>
/// <param name="Key"></param>
/// <param name="Value"></param>
public void WriteLong(string Selection, string Key, long Value)
{
WriteString(Selection, Key, Value.ToString());
}
/// <summary>
/// Write or update an existing double value in the config file
/// </summary>
/// <param name="Selection"></param>
/// <param name="Key"></param>
/// <param name="Value"></param>
public void WriteDouble(string Selection, string Key, double Value)
{
WriteString(Selection, Key, Value.ToString());
}
/// <summary>
/// Writes binary data passed as a Base64 string
/// </summary>
/// <param name="Selection"></param>
/// <param name="Key"></param>
/// <param name="Data"></param>
public void WriteBinary(string Selection, string Key, byte[] Data)
{
try
{
//Write the bytes in Data to a b64 string
WriteString(Selection, Key, Convert.ToBase64String(Data));
}
catch(Exception ex)
{
throw new Exception(ex.Message);
}
}
/// <summary>
/// Reads in a Base64 string and returns the binary bytes.
/// </summary>
/// <param name="Selection"></param>
/// <param name="Key"></param>
/// <param name="vDefault"></param>
/// <returns></returns>
public byte[] ReadBinary(string Selection, string Key, string vDefault="")
{
string b_64 = ReadString(Selection, Key, vDefault);
byte[] _bytes = { 0 };
try
{
//Get bytes from b64 string
_bytes = Convert.FromBase64String(b_64);
//Return bytes
return _bytes;
}
catch(Exception ex)
{
throw new Exception(ex.Message);
}
}
/// <summary>
/// Remove a key and it's value from the config file
/// </summary>
/// <param name="Selection"></param>
/// <param name="Key"></param>
public void RemoveKey(string Selection, string Key)
{
TSelction_Pair pair = new TSelction_Pair();
//Set the data to find
pair.Name = Selection.ToUpper();
pair.Key = Key.ToUpper();
//Check if pair is in hash table
if (ht.ContainsKey(pair))
{
//Remove from hash table
ht.Remove(pair);
}
}
/// <summary>
/// Removes a selection and all it's keys and values
/// </summary>
/// <param name="Selection"></param>
public void RemoveSelection(string Selection)
{
List<TSelction_Pair> paris = new List<TSelction_Pair>();
foreach (TSelction_Pair p in ht.Keys)
{
TSelction_Pair n_pair = p;
//Check if n_pair selection name is equal Selection string
if (n_pair.Name.Equals(Selection, StringComparison.OrdinalIgnoreCase))
{
//Add pair to list
paris.Add(n_pair);
}
}
//Check count of list
if (paris.Count > 0)
{
foreach (TSelction_Pair pp in paris)
{
//Remove the obj from the hash table
ht.Remove(pp);
}
}
paris = new List<TSelction_Pair>();
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment