Read/Write INI file o config file

I find this easy way for read/write some settings to disk, I do not really but google do it :slight_smile: btw here the code

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

/// <summary>
/// Create a New INI file to store or load data
/// </summary>
public class IniFile : MonoBehaviour
{
    private static string path = Application.dataPath + "/inifile.ini";

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

    /// <summary>
    /// Write Data to the INI File
    /// </summary>
    /// <PARAM name="Section"></PARAM>
    /// Section name
    /// <PARAM name="Key"></PARAM>
    /// Key Name
    /// <PARAM name="Value"></PARAM>
    /// Value Name
    public static void IniWriteValue(string Section, string Key, string Value)
    {
        WritePrivateProfileString(Section, Key, Value, path);
    }

    /// <summary>
    /// Read Data Value From the Ini File
    /// </summary>
    /// <PARAM name="Section"></PARAM>
    /// <PARAM name="Key"></PARAM>
    /// <PARAM name="Path"></PARAM>
    /// <returns></returns>
    public static string IniReadValue(string Section, string Key)
    {
        StringBuilder temp = new StringBuilder(255);
        //int i = GetPrivateProfileString(Section, Key, "", temp, 255, this.path);
        GetPrivateProfileString(Section, Key, "", temp, 255, path);
        return temp.ToString();

    }
}

Is static function so dont need to instantiate everywhere, hope work to u too.
Remember the right style of ini file is:

[Section]
Key = Value

that’s it…good work.

1 Like

Good work! But will it work on MacOS / iPhone / Android? I mean, how it sould import kernel32.dll?
Probably using of Resources.Load() is better way? :wink:

It will only work on windows since the unmanaged import is referring to windows dll’s which are not available out side of the windows platform.

Yhea u right, work on windows only -_-,
I’m so accustomed to using windows that I forget its restrictions, bad thing, I hate when it happens, do something good means to do something that everyone can use (in this case that all the pc can interpret), at least as I understand the progress …
btw I made another one and I think it can also be used by machines that do not speak windows hehe :wink:
right?

private static string path = Path.Combine(Application.persistentDataPath, "IniFile.ini");
    private static Dictionary<string, Dictionary<string, string>> IniDictionary = new Dictionary<string, Dictionary<string, string>>();
    private static bool Initialized = false;
    /// <summary>
    /// Sections list
    /// </summary>
    public enum Sections
    {
        Section01,
    }
    /// <summary>
    /// Keys list
    /// </summary>
    public enum Keys
    {
        Key01,
        Key02,
        Key03,
    }

    private static bool FirstRead()
    {
        if (File.Exists(path))
        {
            using (StreamReader sr = new StreamReader(path))
            {
                string line;
                string theSection = "";
                string theKey = "";
                string theValue = "";
                while (!string.IsNullOrEmpty(line = sr.ReadLine()))
                {
                    line.Trim();
                    if (line.StartsWith("[")  line.EndsWith("]"))
                    {
                        theSection = line.Substring(1, line.Length - 2);
                    }
                    else
                    {
                        string[] ln = line.Split(new char[] { '=' });
                        theKey = ln[0].Trim();
                        theValue = ln[1].Trim();
                    }
                    if (theSection == "" || theKey == "" || theValue == "")
                        continue;
                    PopulateIni(theSection, theKey, theValue);
                }
            }
        }
        return true;
    }

    private static void PopulateIni(string _Section, string _Key, string _Value)
    {
        if (IniDictionary.Keys.Contains(_Section))
        {
            if (IniDictionary[_Section].Keys.Contains(_Key))
                IniDictionary[_Section][_Key] = _Value;
            else
                IniDictionary[_Section].Add(_Key, _Value);
        }
        else
        {
            Dictionary<string, string> neuVal = new Dictionary<string, string>();
            neuVal.Add(_Key.ToString(), _Value);
            IniDictionary.Add(_Section.ToString(), neuVal);
        }
    }
    /// <summary>
    /// Write data to INI file. Section and Key no in enum.
    /// </summary>
    /// <param name="_Section"></param>
    /// <param name="_Key"></param>
    /// <param name="_Value"></param>
    public static void IniWriteValue(string _Section, string _Key, string _Value)
    {
        if (!Initialized)
            FirstRead();
        PopulateIni(_Section, _Key, _Value);
        //write ini
        WriteIni();
    }
    /// <summary>
    /// Write data to INI file. Section and Key bound by enum
    /// </summary>
    /// <param name="_Section"></param>
    /// <param name="_Key"></param>
    /// <param name="_Value"></param>
    public static void IniWriteValue(Sections _Section, Keys _Key, string _Value)
    {
        IniWriteValue(_Section.ToString(), _Key.ToString(), _Value);
    }

    private static void WriteIni()
    {
        using (StreamWriter sw = new StreamWriter(path))
        {
            foreach (KeyValuePair<string, Dictionary<string, string>> sezioni in IniDictionary)
            {
                sw.WriteLine("[" + sezioni.Key.ToString() + "]");
                foreach (KeyValuePair<string, string> chiave in sezioni.Value)
                {
                    // value must be in one line
                    string vale = chiave.Value.ToString();
                    vale = vale.Replace(Environment.NewLine, " ");
                    vale = vale.Replace("\r\n", " ");
                    sw.WriteLine(chiave.Key.ToString() + " = " + vale);
                }
            }
        }
    }
    /// <summary>
    /// Read data from INI file. Section and Key bound by enum
    /// </summary>
    /// <param name="_Section"></param>
    /// <param name="_Key"></param>
    /// <returns></returns>
    public static string IniReadValue(Sections _Section, Keys _Key)
    {
        if (!Initialized)
            FirstRead();
        return IniReadValue(_Section.ToString(), _Key.ToString());
    }
    /// <summary>
    /// Read data from INI file. Section and Key no in enum.
    /// </summary>
    /// <param name="_Section"></param>
    /// <param name="_Key"></param>
    /// <returns></returns>
    public static string IniReadValue(string _Section, string _Key)
    {
        if (!Initialized)
            FirstRead();
        if (IniDictionary.ContainsKey(_Section))
            if (IniDictionary[_Section].ContainsKey(_Key))
                return IniDictionary[_Section][_Key];
        return null;
    }
1 Like

BUMB

For anyone who wants to use this, I corrected some errors of the non-Windows version (compatible with Unity 5.3.2f1):

using UnityEngine;
using System.Collections;
using System.IO;
using System.Collections.Generic;
using System;

public class INIWorker {
    private static string path = Path.Combine(Application.persistentDataPath, "IniFile.ini");
    private static Dictionary<string, Dictionary<string, string>> IniDictionary = new Dictionary<string, Dictionary<string, string>>();
    private static bool Initialized = false;
    /// <summary>
    /// Sections list
    /// </summary>
    public enum Sections {
        Section01,
    }
    /// <summary>
    /// Keys list
    /// </summary>
    public enum Keys {
        Key01,
        Key02,
        Key03,
    }

    private static bool FirstRead() {
        if (File.Exists(path)) {
            using (StreamReader sr = new StreamReader(path)) {
                string line;
                string theSection = "";
                string theKey = "";
                string theValue = "";
                while (!string.IsNullOrEmpty(line = sr.ReadLine())) {
                    line.Trim();
                    if (line.StartsWith("[") && line.EndsWith("]"))
                    {
                        theSection = line.Substring(1, line.Length - 2);
                    }
                    else
                    {
                        string[] ln = line.Split(new char[] { '=' });
                        theKey = ln[0].Trim();
                        theValue = ln[1].Trim();
                    }
                    if (theSection == "" || theKey == "" || theValue == "")
                        continue;
                    PopulateIni(theSection, theKey, theValue);
                }
            }
        }
        return true;
    }

    private static void PopulateIni(string _Section, string _Key, string _Value) {
        if (IniDictionary.ContainsKey(_Section)) {
            if (IniDictionary[_Section].ContainsKey(_Key))
                IniDictionary[_Section][_Key] = _Value;
            else
                IniDictionary[_Section].Add(_Key, _Value);
        } else {
            Dictionary<string, string> neuVal = new Dictionary<string, string>();
            neuVal.Add(_Key.ToString(), _Value);
            IniDictionary.Add(_Section.ToString(), neuVal);
        }
    }
    /// <summary>
    /// Write data to INI file. Section and Key no in enum.
    /// </summary>
    /// <param name="_Section"></param>
    /// <param name="_Key"></param>
    /// <param name="_Value"></param>
    public static void IniWriteValue(string _Section, string _Key, string _Value) {
        if (!Initialized)
            FirstRead();
        PopulateIni(_Section, _Key, _Value);
        //write ini
        WriteIni();
    }
    /// <summary>
    /// Write data to INI file. Section and Key bound by enum
    /// </summary>
    /// <param name="_Section"></param>
    /// <param name="_Key"></param>
    /// <param name="_Value"></param>
    public static void IniWriteValue(Sections _Section, Keys _Key, string _Value) {
        IniWriteValue(_Section.ToString(), _Key.ToString(), _Value);
    }

    private static void WriteIni() {
        using (StreamWriter sw = new StreamWriter(path)) {
            foreach (KeyValuePair<string, Dictionary<string, string>> sezioni in IniDictionary) {
                sw.WriteLine("[" + sezioni.Key.ToString() + "]");
                foreach (KeyValuePair<string, string> chiave in sezioni.Value) {
                    // value must be in one line
                    string vale = chiave.Value.ToString();
                    vale = vale.Replace(Environment.NewLine, " ");
                    vale = vale.Replace("\r\n", " ");
                    sw.WriteLine(chiave.Key.ToString() + " = " + vale);
                }
            }
        }
    }
    /// <summary>
    /// Read data from INI file. Section and Key bound by enum
    /// </summary>
    /// <param name="_Section"></param>
    /// <param name="_Key"></param>
    /// <returns></returns>
    public static string IniReadValue(Sections _Section, Keys _Key) {
        if (!Initialized)
            FirstRead();
        return IniReadValue(_Section.ToString(), _Key.ToString());
    }
    /// <summary>
    /// Read data from INI file. Section and Key no in enum.
    /// </summary>
    /// <param name="_Section"></param>
    /// <param name="_Key"></param>
    /// <returns></returns>
    public static string IniReadValue(string _Section, string _Key) {
        if (!Initialized)
            FirstRead();
        if (IniDictionary.ContainsKey(_Section))
            if (IniDictionary[_Section].ContainsKey(_Key))
                return IniDictionary[_Section][_Key];
        return null;
    }
}
4 Likes

Sorry for bumping this thread again but I was wonder how and where should I call this script? I don’t really code a lot in c#, I mostly use unity script.

@batman202012 you dont have to put it anywhere because this script have static functions , you just use it , e.g :

void Start()
{
IniFile.IniWriteValue("Stats","Time",_inTime.ToString());
}
1 Like

So I got a few questions.

This is certainly very useful, now I just need to figure this out:

  1. How to read all the keys in a section?
  2. How to reference all the keys in a section, and values in a List?
  3. How to now change the values for each referenced keys, values via the changed values from the created list?

This should be my starting point and I should be able to figure the rest out after that.

Thank you for the help in advance,

KZ

HI,

I use this here : https://forum.unity3d.com/threads/text-to-speech-dll-for-windows-desktop.56038/page-3#post-2410238

//
using UnityEngine;
using System.Collections;
using Microsoft.Win32;
using System.Runtime.InteropServices;
//

void Start()
{
   // Info (64Bits OS):
   // Executing Windows\sysWOW64\speech\SpeechUX\SAPI.cpl brings up a Window that displays (!) all of the 32 bit Voices
   // and the current single 64 bit Voice "Anna".

   // HKEY_LOCAL_MACHINE\\SOFTWARE\Microsoft\Speech\\Voices\\Tokens\\xxxVOICExxxINSTALLEDxxx\\Attributes >>> (Name)
   const string speechTokens = "Software\\Microsoft\\Speech\\Voices\\Tokens";

   using (RegistryKey registryKey = Registry.LocalMachine.OpenSubKey(speechTokens))
   {
       VoiceNumber = registryKey.SubKeyCount; // key found not mean true voice number !!!
       VoiceNames  = new string[VoiceNumber + 1];
       VoiceNumber = 0;
  
       foreach (var regKeyFound in registryKey.GetSubKeyNames())
       {
           //Debug.Log(regKeyFound);
           string finalKey = "HKEY_LOCAL_MACHINE\\Software\\Microsoft\\Speech\\Voices\\Tokens\\" + regKeyFound + "\\Attributes";
           //Debug.Log(finalKey);
           string gotchaVoiceName = "";
           gotchaVoiceName = (string)Registry.GetValue (finalKey, "Name", "");

           if (gotchaVoiceName != "")
           {
               //Debug.Log("Langage Name = " + gotchaVoiceName);
               VoiceNumber++; // increase the real voice number..
               VoiceNames[VoiceNumber ] = gotchaVoiceName;
           }
       }
   }
  
   // return 0 >>> Init ok
   if (VoiceNumber != 0)
   {
       VoiceInit =  Uni_Voice_Init();
   } else VoiceInit = 1;

}

This seems to be something different unless I just simply do not understand it. How can I implement this to read the ini stuff of a file rather than the registry?

I just tried it, but it does not work at all.

Works like a charm in 2017.3, a million thanks!