Laden...

IniReader

Erstellt von ZiMD vor 18 Jahren Letzter Beitrag vor 16 Jahren 28.296 Views
ZiMD Themenstarter:in
564 Beiträge seit 2005
vor 18 Jahren
IniReader

Hi

ich hab mir hier eine kleine dll zum lesen und schreiben von ini-dateien geschrieben


using System;
using System.Text.RegularExpressions;

namespace System
{
    namespace IO
    {
        public class IniReader
        {
            private inidatei[] inizeilen;
            private string datei = "";

            public IniReader(string file)
            {
                datei = file;
                string[] iniread = File.ReadAllLines(file);
                inizeilen = new inidatei[iniread.Length];
                Regex reg1 = new Regex(@"^[^=]*\[[^\]]*\][^=]*$");
                Regex reg2 = new Regex(@"^[^=]+=[^=]+$");
                for (int i = 0; i < inizeilen.Length; i++)
                {
                    if (reg1.Match(iniread[i]).Success)
                    {
                        inizeilen[i].befehl = "";
                        inizeilen[i].wert = "";
                        inizeilen[i].text = iniread[i];
                    }
                    else if (reg2.Match(iniread[i]).Success)
                    {
                        string[] temp = iniread[i].Split('=');
                        inizeilen[i].befehl = temp[0].Trim();
                        inizeilen[i].wert = temp[1].Trim();
                        inizeilen[i].text = "";
                    }
                    else
                    {
                        inizeilen[i].befehl = "";
                        inizeilen[i].wert = "";
                        inizeilen[i].text = "";
                    }
                }
            }

            private struct inidatei
            {
                public string befehl;
                public string wert;
                public string text;
            }

            public string Get(string befehl)
            {
                string returnstring = "";
                foreach (inidatei i in inizeilen)
                {
                    if (i.befehl == befehl)
                    {
                        returnstring = i.wert;
                    }
                }
                return returnstring;
            }

            public bool Set(string befehl, string wert)
            {
                bool success = false;
                for (int i = 0; i < inizeilen.Length; i++)
                {
                    if (inizeilen[i].befehl == befehl)
                    {
                        inizeilen[i].wert = wert;
                        success = true;
                    }
                }
                if (!success)
                {
                    return success;
                }
                StreamWriter writer = new StreamWriter(datei);
                foreach (inidatei i in inizeilen)
                {
                    if (!String.IsNullOrEmpty(i.text))
                    {
                        writer.WriteLine(i.text);
                    }
                    else if(!String.IsNullOrEmpty(i.befehl) && !String.IsNullOrEmpty(i.wert))
                    {
                        writer.WriteLine(i.befehl + "=" + i.wert);
                    }
                }
                writer.Close();
                return success;
            }
        }
    }
}

habt ihr noch verbesserungsvorschläge?

edit: hier nochmal der richtige regex:

Regex reg1 = new Regex(@"[=][[^]]][=]*$");
Regex reg2 = new Regex(@"
[=]+=[=]+$");

D
481 Beiträge seit 2005
vor 18 Jahren

Ich hätte da eine, damit du n weniger Code hast 😉

In dem else-Bereich:


else if (reg2.Match(iniread[i]).Success)
                    {
                        string[] temp = iniread[i].Split('=');
                        inizeilen[i].befehl = temp[0].Trim();
                        inizeilen[i].wert = temp[1].Trim();
                        inizeilen[i].text = iniread[i];
                    }

Dann musste beim wiederreinschreiben nur noch sagen:


//writer.WriteLine(i.befehl + "=" + i.wert);
writer.WriteLine(i.text);

Sonst wäre mir nichts aufgefallen. Gute Arbeit.

Dexter

Programmierer sind Maschinen die Koffein in Quellcode umsetzen.

ZiMD Themenstarter:in
564 Beiträge seit 2005
vor 18 Jahren

ich habs noch ein wenig verbessert:


using System;
using System.Text.RegularExpressions;

namespace System
{
    namespace IO
    {
        public class IniReader
        {
            private inidatei[] inizeilen;
            private string datei = "";

            public IniReader(string file)
            {
                datei = file;
                string[] iniread = File.ReadAllLines(file);
                inizeilen = new inidatei[iniread.Length];
                Regex reg = new Regex(@"^[^=]+=[^=]+$");
                for (int i = 0; i < inizeilen.Length; i++)
                {
                    if (reg.Match(iniread[i]).Success)
                    {
                        string[] temp = iniread[i].Split('=');
                        inizeilen[i].befehl = temp[0].Trim();
                        inizeilen[i].wert = temp[1].Trim();
                        inizeilen[i].text = "";
                    }
                    else
                    {
                        inizeilen[i].befehl = "";
                        inizeilen[i].wert = "";
                        inizeilen[i].text = iniread[i];
                    }
                }
            }

            private struct inidatei
            {
                public string befehl;
                public string wert;
                public string text;
            }

            public string Get(string befehl)
            {
                string returnstring = "";
                foreach (inidatei i in inizeilen)
                {
                    if (i.befehl == befehl)
                    {
                        returnstring = i.wert;
                    }
                }
                return returnstring;
            }

            public bool Set(string befehl, string wert)
            {
                bool success = false;
                for (int i = 0; i < inizeilen.Length; i++)
                {
                    if (inizeilen[i].befehl == befehl)
                    {
                        inizeilen[i].wert = wert;
                        success = true;
                    }
                }
                if (!success)
                {
                    return success;
                }
                StreamWriter writer = new StreamWriter(datei);
                for(int i = 0; i < inizeilen.Length; i++)
                {
                    if (!String.IsNullOrEmpty(inizeilen[i].befehl))
                    {
                        if (i == (inizeilen.Length - 1))
                        {
                            writer.Write(inizeilen[i].befehl + "=" + inizeilen[i].wert);
                        }
                        else
                        {
                            writer.WriteLine(inizeilen[i].befehl + "=" + inizeilen[i].wert);
                        }
                    } 
                    else
                    {
                        if (i == (inizeilen.Length - 1))
                        {
                            writer.Write(inizeilen[i].text);
                        }
                        else
                        {
                            writer.WriteLine(inizeilen[i].text);
                        }
                    }
                }
                writer.Close();
                return success;
            }
        }
    }
}

ein wenig mehr code aber dafür bleibt alles erhalten

V
842 Beiträge seit 2003
vor 18 Jahren

Du könntest eventuell noch Kommentare mit aufnehmen in deinem regulären Ausdruck. Habe sowas auch mal in C++ geschrieben (wo es leider keine RegEx gibt, aber trotzdem danke für den RegEx, werde mir glaube ich mal Boost zulegen und das damit machen) und Kommentare rausgefiltert, die mit # eingeleitet werden. Außerdem gibt es bei mir neben Key=Value noch Chapters was sicher auch interessant wäre.
Beispiel:
[chapter]
key=value #comment

Was ich nicht implementiert habe ist das die Kommentare beim schreiben erhalten bleiben bzw. man welche anfügen kann, aber ich glaube auch nicht das das für das automatische schreiben interessant wäre. Ich entferene sie nur beim lesen.

Außerdem habe ich noch 2 Routinen geschrieben die eine ganzzahlige Zahl und eine Fließkommazahl zurückliefern, wobei das eher nen kleines Feature ist. Evtl. könnte man die Klasse auch zu einem Template (Generic) umwandeln (für Vorschläge für sowas, wäre ich jederzeit offen, egal ob in C# oder sonst was 🙂 ).

Vellas

L
667 Beiträge seit 2004
vor 18 Jahren

Man könnte auch die einschlägigen Funktionen aus der Kernel32.dll importieren, also GetPrivateProfileString usw. - und wäre dann in 5 Minuten mit der Klasse fertig und hätte weniger als die Hälfte des Codes.

Wenn man das Rad aber unbedingt neu erfinden will, dann sieht Dein Vorschlag super aus 🙂

"It is not wise to be wise" - Sun Tzu

4.506 Beiträge seit 2004
vor 18 Jahren

Hallo zusammen,

für mich machen .INI Dateien nur noch mit älteren Betriebssystemen Sinn. Ich würde heutzutage eher auf XML setzen.

XML ist durch Schemadefinitionen und Transformationsmöglichkeiten weitaus flexibler.

Aber damals hatten auch INI Dateien ihre Berechtigung, und würd sie trotzdem nur für Settings benutzen.

Ansonsten würde auch ich sagen, dass das gut gelöst ist.

Ciao
Norman-Timo

A: “Wie ist denn das Wetter bei euch?”
B: “Caps Lock.”
A: “Hä?”
B: “Na ja, Shift ohne Ende!”

S
8.746 Beiträge seit 2005
vor 18 Jahren

Oder einfach NINI verwenden, welches transparent XML-Konfig, INIs und die Registry nutzen kann.

ZiMD Themenstarter:in
564 Beiträge seit 2005
vor 18 Jahren

Original von Vellas
Du könntest eventuell noch Kommentare mit aufnehmen in deinem regulären Ausdruck. Habe sowas auch mal in C++ geschrieben (wo es leider keine RegEx gibt, aber trotzdem danke für den RegEx, werde mir glaube ich mal Boost zulegen und das damit machen) und Kommentare rausgefiltert, die mit # eingeleitet werden.

ok sind drin

Original von Vellas
Außerdem gibt es bei mir neben Key=Value noch Chapters was sicher auch interessant wäre.
Beispiel:
[chapter]
key=value #comment

ja aber wofür kann man die gebrauchen?
ich dachte immer die dienen nur beim ändern im notepad zur orientierung

Original von Vellas
Evtl. könnte man die Klasse auch zu einem Template (Generic) umwandeln (für Vorschläge für sowas, wäre ich jederzeit offen, egal ob in C# oder sonst was smile

wenn du mir sagst wie 😜

Original von Lynix
Wenn man das Rad aber unbedingt neu erfinden will, dann sieht Dein Vorschlag super aus 🙂

Danke 😁

Original von norman_timo
Aber damals hatten auch INI Dateien ihre Berechtigung, und würd sie trotzdem nur für Settings benutzen.

Dafür sind sie gedacht 🙂

der neue code:


using System;
using System.Text.RegularExpressions;

namespace System
{
    namespace IO
    {
        public class IniReader
        {
            private inidatei[] inizeilen;
            private string datei = "";

            public IniReader(string file)
            {
                datei = file;
                string[] iniread = File.ReadAllLines(file);
                inizeilen = new inidatei[iniread.Length];
                Regex reg = new Regex(@"^(?<befehl>([^=])+)=(?<wert>([^=#])+)(#(?<kommentar>.*))?$");
                for (int i = 0; i < inizeilen.Length; i++)
                {
                    Match m = reg.Match(iniread[i]);
                    if (m.Success)
                    {
                        inizeilen[i].befehl = m.Groups["befehl"].Value.Trim();
                        inizeilen[i].wert = m.Groups["wert"].Value.Trim();
                        inizeilen[i].kommentar = m.Groups["kommentar"].Value.Trim();
                        inizeilen[i].text = "";
                    }
                    else
                    {
                        inizeilen[i].befehl = "";
                        inizeilen[i].wert = "";
                        inizeilen[i].kommentar = "";
                        inizeilen[i].text = iniread[i];
                    }
                }
            }

            private struct inidatei
            {
                public string befehl;
                public string wert;
                public string kommentar;
                public string text;
            }

            public string[] Get(string befehl)
            {
                string[] returnstring = new string[2];
                returnstring[0] = "";
                returnstring[1] = "";
                foreach (inidatei i in inizeilen)
                {
                    if (i.befehl == befehl)
                    {
                        returnstring[0] = i.wert;
                        returnstring[1] = i.kommentar;
                    }
                }
                return returnstring;
            }

            public bool Set(string befehl, string wert)
            {
                bool success = false;
                for (int i = 0; i < inizeilen.Length; i++)
                {
                    if (inizeilen[i].befehl == befehl)
                    {
                        inizeilen[i].wert = wert;
                        success = true;
                    }
                }
                if (!success)
                {
                    return success;
                }
                StreamWriter writer = new StreamWriter(datei);
                for(int i = 0; i < inizeilen.Length; i++)
                {
                    if (!String.IsNullOrEmpty(inizeilen[i].befehl))
                    {
                        writer.Write(inizeilen[i].befehl + "=" + inizeilen[i].wert);
                        if (!String.IsNullOrEmpty(inizeilen[i].kommentar)) writer.Write(" #" + inizeilen[i].kommentar);
                        if(i != (inizeilen.Length - 1))
                        {
                            writer.WriteLine();
                        }
                    } 
                    else
                    {
                        writer.Write(inizeilen[i].text);
                        if(i != (inizeilen.Length - 1))
                        {
                            writer.WriteLine();
                        }
                    }
                }
                writer.Close();
                return success;
            }
        }
    }
}

das mit dem array als rückgabe bei der get funktion gefällt mir nicht so

Regex reg = new Regex(@"(?<befehl>([=])+)=(?<wert>([^=#])+)(#(?<kommentar>.*))?$");

49.485 Beiträge seit 2005
vor 18 Jahren

Hallo ZiMD,

ich dachte immer die dienen nur beim ändern im notepad zur orientierung

Die Abschnitte sind durchaus relevant. So könnten bei einem Spiel die gleichen Einstellungen in je einem Chapter für jeden der Spieler verwendet werden, z.B.

[Player1]
name=hugo
AccelerateKey=A
BreakKey=Y

[Player2]
name=egon
AccelerateKey=Num8
BreakKey=Num2

herbivore

ZiMD Themenstarter:in
564 Beiträge seit 2005
vor 18 Jahren

gut dann hier noch eine überarbeitete version

ich hab auch noch die rückgabe beim get geändert


using System;
using System.Text.RegularExpressions;

namespace System
{
    namespace IO
    {
        public class IniReader
        {
            private inidatei[] inizeilen;
            private string datei = "";

            public IniReader(string file)
            {
                datei = file;
                string abschnitt = "";
                string[] iniread = File.ReadAllLines(file);
                inizeilen = new inidatei[iniread.Length];
                Regex reg1 = new Regex(@"^(?<befehl>([^=])+)=(?<wert>([^=#])+)(#(?<kommentar>.*))?$");
                Regex reg2 = new Regex(@"^[^=]*\[(?<abschnitt>([^\]]*))\][^=]*$");
                for (int i = 0; i < inizeilen.Length; i++)
                {
                    Match m1 = reg1.Match(iniread[i]);
                    Match m2 = reg2.Match(iniread[i]);
                    if (m1.Success)
                    {
                        inizeilen[i].befehl = m1.Groups["befehl"].Value.Trim();
                        inizeilen[i].wert = m1.Groups["wert"].Value.Trim();
                        inizeilen[i].kommentar = m1.Groups["kommentar"].Value.Trim();
                        inizeilen[i].abschnitt = abschnitt;
                        inizeilen[i].text = "";
                    }
                    else
                    {
                        if (m2.Success)
                        {
                            abschnitt = m2.Groups["abschnitt"].Value.Trim();
                        }
                        inizeilen[i].befehl = "";
                        inizeilen[i].wert = "";
                        inizeilen[i].kommentar = "";
                        inizeilen[i].abschnitt = "";
                        inizeilen[i].text = iniread[i];
                    }
                }
            }

            private struct inidatei
            {
                public string befehl;
                public string wert;
                public string kommentar;
                public string abschnitt;
                public string text;
            }

            public struct Return
            {
                public string Command;
                public string Value;
                public string Comment;
                public string Chapter;
            }

            public Return Get(string befehl)
            {
                Return rueckgabe = new Return();
                rueckgabe.Command = befehl;
                rueckgabe.Value = "";
                rueckgabe.Comment = "";
                foreach (inidatei i in inizeilen)
                {
                    if (i.befehl == befehl)
                    {
                        rueckgabe.Value = i.wert;
                        rueckgabe.Comment = i.kommentar;
                        rueckgabe.Chapter = i.abschnitt;
                    }
                }
                return rueckgabe;
            }

            public Return[] GetChapter(string chapter)
            {
                Return[] rueckgabe = new Return[0];
                foreach (inidatei i in inizeilen)
                {
                    if (i.abschnitt == chapter)
                    {
                        Array.Resize(ref rueckgabe, rueckgabe.Length + 1);
                        rueckgabe[rueckgabe.Length - 1].Chapter = chapter;
                        rueckgabe[rueckgabe.Length - 1].Command = i.befehl;
                        rueckgabe[rueckgabe.Length - 1].Comment = i.kommentar;
                        rueckgabe[rueckgabe.Length - 1].Value = i.wert;
                    }
                }
                return rueckgabe;
            }

            public bool Set(string befehl, string wert)
            {
                bool success = false;
                for (int i = 0; i < inizeilen.Length; i++)
                {
                    if (inizeilen[i].befehl == befehl)
                    {
                        inizeilen[i].wert = wert;
                        success = true;
                    }
                }
                if (!success)
                {
                    return success;
                }
                StreamWriter writer = new StreamWriter(datei);
                for(int i = 0; i < inizeilen.Length; i++)
                {
                    if (!String.IsNullOrEmpty(inizeilen[i].befehl))
                    {
                        writer.Write(inizeilen[i].befehl + "=" + inizeilen[i].wert);
                        if (!String.IsNullOrEmpty(inizeilen[i].kommentar)) writer.Write(" #" + inizeilen[i].kommentar);
                        if(i != (inizeilen.Length - 1))
                        {
                            writer.WriteLine();
                        }
                    } 
                    else
                    {
                        writer.Write(inizeilen[i].text);
                        if(i != (inizeilen.Length - 1))
                        {
                            writer.WriteLine();
                        }
                    }
                }
                writer.Close();
                return success;
            }
        }
    }
}

V
842 Beiträge seit 2003
vor 18 Jahren

Original von ZiMD
wenn du mir sagst wie 😛

Sagte nicht das du es machen sollst, dass war ne Überlegung die ich mal angestellt habe, da ich mit einer doppeltverschatelten Map arbeite. Map besteht aus key und value, dabei ist der Key nen String und der zweite eine Map mit String für key und value. Da ich demnächst erst wieder mit C# beginne und dann auch in Version 2, weiß ich nicht genau wie es da aussieht (ich denke aber mal nicht wesentlich anders). In C++ würde die Map so aussehen:

map<string, map<string, string> >

Aber ich glaube nicht das es sich lohnt das umzustellen, da man wohl hauptsächlich Strings benötigt und entsprechende Routinen um an einen Zahlenwert zu kommen, habe ich ja auch dabei. Hatte ich nur mal erwähnt, vllt. hätte mir ja jemand was gegenteiliges sagen können. 😉

Ansonsten finde ich die Klasse aber auch sehr gut von dir.🙂

Zur Berechtigung von ini-Dateien, so finde ich sie immer noch sehr praktisch. Sicher braucht man manchmal eine flexiblere Möglichkeit um Daten zu speichern, wo XML von Vorteil wäre, aber wie gesagt, wenn es um das reine Speichern von Settings geht bleibe ich bei diesen Dateien. Die kenne ich und habe schon alles was ich dafür brauche 🙂 (und vor allem war meine erste Version in C und da hing schon über ne Woche Arbeit dran, wegen der Speicherverwaltung).

Vellas

-
885 Beiträge seit 2004
vor 18 Jahren

Also bei mir bringt er einen Fehler bei "reg2" -> parsing "[=][(?<abschnitt>([^]]))][^=]*$" - Too many )'s.

Frage: Darf man GetChapter-Methode mit der entsprechenden Structure weiterbenutzen? 🙂

ZiMD Themenstarter:in
564 Beiträge seit 2005
vor 18 Jahren

Original von -acid-
Also bei mir bringt er einen Fehler bei "reg2" -> parsing "[=][(?<abschnitt>([^]]))][^=]*$" - Too many )'s.

Frage: Darf man GetChapter-Methode mit der entsprechenden Structure weiterbenutzen? 🙂

es muss ja auch so heißen:

Regex reg2 = new Regex(@"[=][(?<abschnitt>([^]]))][^=]*$");

der c# code hier im forum löscht die \ zeichen

E
100 Beiträge seit 2006
vor 18 Jahren

Ini in der .NET Welt ?

Das paßt irgendwie nicht zusammen...

Also ich würde auf jeden Fall XML nehmen 🙂

-
885 Beiträge seit 2004
vor 18 Jahren

Geht bei mir aber nicht, weil ich eine Klasse geschrieben, die mit ini-Files bzw mit der Wert=Value Struktur arbeiten muss. Diese Klasse wird zum Bearbeiten bzw. Auslesen von solchen Dateien benötigt, damit mein Programm die Einträge verarbeiten kann.

ZiMD Themenstarter:in
564 Beiträge seit 2005
vor 18 Jahren

ok wir haben ein dos prog das von selbst rar dateien aus einem ordner holt und sie in einem anderen als zips speichert

jetzt könnte man zur angabe der pfade natürlich ne riesige xml datei holen, oder eine 2 zeilige ini

was ist besser?

-
885 Beiträge seit 2004
vor 18 Jahren

ZiMD die wird dann bestimmt nicht "riesig" 😉

<settings>
<wert1>value1</wert1>
<wert2>value2</wert2>
</settings>

Wir bewegen uns hier im Bytebereich. Aber trotzdem: Manchmal gibts noch sinvolle Einsatzgebiete für Inis.

ZiMD Themenstarter:in
564 Beiträge seit 2005
vor 18 Jahren

Original von -acid-
ZiMD die wird dann bestimmt nicht "riesig" 😉

<settings>
<wert1>value1</wert1>
<wert2>value2</wert2>
</settings>

Wir bewegen uns hier im Bytebereich. Aber trotzdem: Manchmal gibts noch sinvolle Einsatzgebiete für Inis.

ich hatte jetzt eher an die monster xmls gedacht die mir vs erstellt

-
885 Beiträge seit 2004
vor 18 Jahren

Ah, ich kenne mich leider mit Regex noch nicht so gut aus. Bin noch nicht 100% dahinter gekommen, daher sind mir auch nicht die fehlenden "&quot; aufgefallen. Leider filtert er bei mir meine Sections nicht. Kannst du mir helfen?

Datei:

[box1]
zeile1=wert1
zeile2="wert2"
Zeile3=wert3 ;kommentar

[box2]
zeile1=wert4
zeile2="wert5"
Zeile3=wert6

ZiMD Themenstarter:in
564 Beiträge seit 2005
vor 18 Jahren

sollte alles gehen außen dass kommentare mit einem # eingeleitet werden

49.485 Beiträge seit 2005
vor 18 Jahren

Hallo ZiMD,

wenn ich mich recht entsinne, dann ist Semikolon das "offizielle" Kommentarzeichen für ini-Dateien.

herbivore

ZiMD Themenstarter:in
564 Beiträge seit 2005
vor 18 Jahren

ich denk soviel sollte jeder können dass er sich das selber umschreiben kann 🙂

49.485 Beiträge seit 2005
vor 18 Jahren

Hallo ZiMD,

könnten sollte das jeder, aber wäre es nicht besser, wenn der Standard Standard wäre? 🙂

herbivore

-
885 Beiträge seit 2004
vor 18 Jahren

Kommentare werden bei mir mit ";" eingeleitet (habe ich aber auch im Regex abgeändert). Wie schon geasgt, der zweite Regex funzt bei mir nicht. Aber ich schaue nochmal...

V
842 Beiträge seit 2003
vor 18 Jahren

Beide Zeichen sind als Kommentarzeichen sehr verbreitet in Windows. Kommt oft drauf an, welches der beiden Zeichen für Einstellungen benötigt werden. Das # scheint aber aus der Unix-Welt eingeführt worden zu sein. Das Semikolon ist noch verbreiteter, wobei es auch oft drauf ankommt ob eines der beiden Zeichen für Einstellungen benutzt wird. Für eigene Anwendungen ist es aber sicher kein Problem sich für ein Kommentarzeichen zu entscheiden. Man kann ja sonst auch beide Abfangen.

Einen Standard zu ini-Dateien habe ich aber nicht gefunden, auch zu den Kommentarzeichen erhält man recht wenig Informationen. Dafür umsomehr zum allgemeinen Aufbau von ini-Dateien. Die meisten ini-Dateien sind eh nicht kommentiert.

S
37 Beiträge seit 2005
vor 18 Jahren

Hy Jungs, hier mal mein Ansatz:


using System;
using System.Collections.Generic;
using System.Text;
using System.Text.RegularExpressions;
using System.IO;


/// <summary>
/// Die KLasse Ini ist  Repräsentant einer ini-Profile-Datei.
/// Die Klasse stellt alle Funktionen bereit, die sonst nur über die Win32-Api 
/// zur Verfügung gestellt werden. Kommentare werden noch nicht akzeptiert.
///  und rausgefilter. wird ergänzt.
/// </summary>
public class Ini
{
    private Dictionary<string, Dictionary<string, string>> Areas = new Dictionary<string,Dictionary<string,string>>();
    private Regex RArea = new Regex(@"\W*\[([0-9a-zA-Z -\\/]+)\](?>.*)");
    private Regex RKey = new Regex(@"\W*([0-9a-zA-Z -\\/]*=[0-9a-zA-Z -\\/]*).*");
    private String FileName;
    
    public Ini(string File)
    {
        this.FileName = File;
        this.Init();
    }

    public Dictionary<string, Dictionary<string, string>> GetProfile()
    {
        FileInfo theIni = new FileInfo(this.FileName);
        StreamReader IniFile = theIni.OpenText();
        string tmp;
        String ActArea = "";
        do
        {
            tmp = IniFile.ReadLine();
            if (tmp != null)
            {
                try
                {
                    Match m = this.RArea.Match(tmp);
                    if (m.Success)
                    {
                        ActArea = m.Value.ToString();
                        if (!this.Areas.ContainsKey(m.Value.ToString()))
                            this.Areas.Add(m.Value.ToString(), new Dictionary<string,string>());
                    }
                    else
                    {
                        if (ActArea != "")
                        {
                            if (this.Areas.ContainsKey(ActArea))
                            {
                                Match mk = RKey.Match(tmp);
                                if (mk.Success)
                                {
                                    string[] Str = mk.Value.ToString().Split('=');
                                    if (!this.Areas[ActArea].ContainsKey(Str[0].ToString()))
                                    {
                                        this.Areas[ActArea].Add(Str[0], Str[1]);
                                    }
                                    else
                                    {
                                        this.Areas[ActArea][Str[0].ToString()] = Str[1].ToString();
                                    }
                                }
                            }
                        }
                    }

                }
                catch { }
            }
        } while (tmp != null);
        IniFile.Close();
        return Areas;
    }
    
    public Dictionary<string, string> GetKeys(string section)
    {
        try
        {
            return Areas[section];
        }
        catch 
        {
            Dictionary<string, string> Error = new Dictionary<string, string>();
            Error.Add("Error", "Specified Section not Available!!!");
            return Error;
        }
    }
    
    public void Init()
    {
        this.GetProfile();

    }

   
   public void Close(Boolean Backup)
    {
        if (Backup)
        {
            this.WriteProfile(true);
        }
        else { this.WriteProfile(false); }
    }

    public void Close()
    {
        this.WriteProfile(false);
    }
    
    public String GetValue(String area, String Key)
    {
        try
        {
            return this.Areas[area][Key];
        }
        catch
        {
            return "Error";
        }
    }

    public Boolean SetKey(String Section, String Key, String Value)
    {
        Section = @"[" + Section + @"]";
        try
        {
            if (Areas.ContainsKey( Section ))
            {
                if (Areas[Section].ContainsKey(Key))
                {
                    Areas[Section][Key] = Value;
                }
                else
                {
                    Areas[Section].Add(Key, Value);
                }

            }
            else
            {
                Dictionary<string, string> KV = new Dictionary<string, string>();
                KV.Add(Key, Value);
                Areas.Add(Section , KV);
            }
            return true;
        }
        catch { return false; }
    }
    
    public Boolean SetKey(String Section, String Key, String Value, bool direct)
    {
        try
        {
            if (Areas.ContainsKey(Section))
            {
                if (Areas[Section].ContainsKey(Key))
                {
                    Areas[Section][Key] = Value;
                }
                else
                {
                    Areas[Section].Add(Key, Value);
                }

            }
            else
            {
                Dictionary<string, string> KV = new Dictionary<string, string>();
                KV.Add(Key, Value);
                Areas.Add(@"[" + Section +"]" , KV);
            }
            if (direct)
            {
                this.WriteProfile(false);
            }
            return true;
        }
        catch { return false; }
    }

    public Boolean WriteProfile(Boolean bc)
    {   
        if (bc)  
        File.Copy(this.FileName, this.FileName + "_", true);
        StreamWriter wr = new StreamWriter(this.FileName, false);
                  
            foreach (string Ar in this.Areas.Keys)
            {
                wr.WriteLine( Ar);
                foreach (string KK in this.Areas[Ar].Keys)
                {
                    wr.WriteLine(KK.ToString() + "=" + Areas[Ar][KK.ToString()].ToString());
                }
            }
        wr.Close();
        return true;
    }

     ~Ini()
    {
        this.Close(false);

    }
    
}

Xml sollte allerdings wirklich die bessere Lösung sein...
ist nur so dass man auf nem Unix sonst keine .INIs handlen kann...

  1. :rolleyes:98,5 % aller IT-Probleme werden durch Fehlfunktionen des Layer 8 ausgelöst!! :rolleyes:8)
P
3 Beiträge seit 2006
vor 18 Jahren
INIReader - Beispiele? pls :(

Hi leute,
bin nun auch mal auf .Net umgestiegen von vb6 -> c#, bräucht nur noch ne Starthilfe wie ich genau, mit dieser InI-Klasse, einen Schreib-/Lese-Zugriff mache 😠


// Neues Objekt der Klasse erstellen, um Methoden der Klasse übers Objekt nutzen zu können
IniReader Iniobj = new IniReader(txt_appdir.Text + "\\AppSettings.ini");

// Wenns Kapitel/Abschnitt net gibt...
if (Iniobj.GetChapter("[AppSettings_" + txt_app.Text +"]"  == ""))
{
// Neue Einträge in ini-Datei schreiben
Iniobj.Set("abschnitt", "[AppSettings_" + txt_app.Text + "]");
Iniobj.Set("wert", "Dir=" + txt_app.Text);
}

Damit wollt ich in der .Ini-Datei nach diesem Kapitel "[AppSettings" + txt_app.Text

  • "]" schaun und wenns net existiert, neues Kapitel mit Werten anlegen.

Fehler:
System.ArgumentException: "[=][(?<abschnitt>([^]]))][^=]*$" wird analysiert - Zu viele )-Zeichen.
Irgendwas, mach ich da falsch 🙁

ZiMD Themenstarter:in
564 Beiträge seit 2005
vor 18 Jahren

http://stuff.mybfk.de/class1.cs

Das gibts den richtigen Code.

Steig besser auf XML um.

P
3 Beiträge seit 2006
vor 18 Jahren

Öhm, die Klasse ich doch die selbe wie auf Seite 1 oder was ist an dieser anders?

Jop, ist leider so das mein Programm nicht das einzigste Programm ist was auf jene Ini-Datei zugreift, meins sollte quasi nur die InI-Datei ändern.

ZiMD Themenstarter:in
564 Beiträge seit 2005
vor 18 Jahren

http://stuff.mybfk.de/Class1.cs

/edit: Da gehts auch 😉

P
3 Beiträge seit 2006
vor 18 Jahren

Sehe keinen Unterschied zwischen dieser Klasse und der Klasse auf Seite 1 xD

INIReader - Beispiele <-

Oder was ist den falsch an meinem code?

ZiMD Themenstarter:in
564 Beiträge seit 2005
vor 18 Jahren

In der

 Klasse hier im Forum werden einigen Zeichen verschluckt
M
28 Beiträge seit 2006
vor 18 Jahren
KeyValue bleibt leer

Hallo,

ich bin gerade mit einem IniReader beschäftigt. Einige Anregungen habe ich aus bestehenden IniReadern und auch einiges, z.B. die regulären Ausdrücke hier aus dem Thread.
Ich habe zwei Klassen. Eine Klasse nennt sich IniLine und eine weitere Klasse nennt sich FlatIni.

FlatIni hält eine List<IniLine> iniLines;

Nachdem ich die Ini-Datei zeilenweise in ein string[] eingelesen habe, splitte ich mit folgender Instanzmethode die Ini in Keys, Values und Comments auf.

Beispiel:

Key Value
aKeyDef=Ein KeyValue

Comment #Kommentar


private bool SplitIntoKeys()
			{
				if (stringData.Length > 0)
				{
					// Make new List for IniKeys					
					iniLines = new List<IniLine>();
					
					// Sets regular expression
					Regex RegAusd = new Regex  (@"W*([0-9a-zA-Z -\/]*=[0-9a-zA-Z -\/]*).*");
					
					// 
					foreach (string aLine in stringData) 
					{
						if (aLine != "")
						{
							IniLine NewLine = new IniLine();

							Match M1 = RegAusd.Match(aLine);
																					
							if (M1.Success)
							{																
								string[] Str = M1.Value.ToString().Split('=');
								
								NewLine.KeyName = Str[0];
								NewLine.KeyValue = Str[1];
								NewLine.IsKey = true;																								
							}
							else								
								NewLine.Comment = aLine;

							// 
							iniLines.Add(NewLine);
						}
					}
					
					if (iniLines.Count > 0)
						return true;
					else
						return false;
				}
				else 
					return false;
			}

Beim debuggen scheint alles in Ordnung zu sein. Die IniDatei enthält values und die Zeile

NewLine.KeyValue = Str[1];

wird korrekt durchlaufen und es befinden sich Werte in Str[1]

Wieder zurück im Hauptformular soll das Ergebniss in Listviews angezeigt.
An der Stelle habe ich die Werte mal in eine RichTextBox schreiben lassen.
Die Values blieben leer. Die KeyNames waren gefüllt und auch Kommentare gab es.
Nun weiss ich aber, dass es Values gibt.

Eine Idee woran es liegen könnte?
Ich poste auch gerne noch weiteren Code wenn gewünscht.

Gruß
musicones

1.820 Beiträge seit 2005
vor 16 Jahren
IniReader

Hallo!

Bzgl. Ini-Dateien gibt es nun einen weiteren Thread. Dieser hier ist mir erst gestern zufällig aufgefallen, als ich den anderen gesucht habe 8o.

Link zur Ini-Datei-Klasse

Nobody is perfect. I'm sad, i'm not nobody 🙁

M
7 Beiträge seit 2007
vor 16 Jahren
Ini Reader/Writer

Falls es jemanden interessiert, man kann Ini-Dateien auch noch anders schreiben bzw. lesen:


    public class IniHelper
    {
        #region Fields

        /// <summary>
        /// Pfad für den user-spezifischen Anwendungspfad ("C:\Dokumente...\#Username#\Anwendungsdaten\Firma\#Appname#")
        /// </summary>
        static internal string userSpecificAppFolder = string.Format(
            "{0}{1}{2}{3}{4}",
            Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData),
            Path.DirectorySeparatorChar,
            "Firma",
            Path.DirectorySeparatorChar,
            Application.ProductName);

        private string iniPath;

        #endregion

        #region DllImport

        [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);

        #endregion

        #region Konstruktor

        /// <summary>
        /// Konstruktor der IniHelper-Klasse
        /// </summary>
        public IniHelper()
        {
            this.iniPath = string.Format(
                "{0}{1}{2}",
                userSpecificAppFolder,
                Path.DirectorySeparatorChar,
                Application.ProductName + ".ini");

            if (!Directory.Exists(userSpecificAppFolder))
                Directory.CreateDirectory(userSpecificAppFolder);
        }

        #endregion

        #region Methods

        /// <summary>
        /// Schreibt einen Wert in die Ini-Datei über [kernel32.dll]
        /// </summary>
        /// <param name="section">Gibt den Abschnitt der Ini-Datei an, in den der Schlüssel geschrieben werden soll</param>
        /// <param name="Key">Gibt Schlüssel der Ini-Datei an, in den der Wert geschrieben werden soll</param>
        /// <param name="Value">Gibt den Wert an, der in die Ini-Datei geschrieben werden soll</param>
        public void IniWriteValue(string section, string Key, string Value)
        {
            WritePrivateProfileString(section, Key, Value, IniPath);
        }

        /// <summary>
        /// Liest einen Wert aus der Ini-Datei über [kernel32.dll]
        /// </summary>
        /// <param name="section">Gibt den Abschnitt der Ini-Datei an, aus dem der Schlüssel gelesen werden soll</param>
        /// <param name="Key">Gibt den Schlüssel der Ini-Datei an, aus dem der Wert gelesen werden soll</param>
        /// <returns>Gibt den Wert zurück, der in der Ini-Datei bei Abschnitt->Schlüssel hinterlegt ist</returns>
        public string IniReadValue(string section, string Key)
        {
            StringBuilder temp = new StringBuilder(255);
            int i = GetPrivateProfileString(section, Key, "", temp, 255, IniPath);

            return temp.ToString();
        }

        #endregion

        #region Propertys

        public string IniPath
        {
            get
            {
                return this.iniPath;
            }
            set
            {
                this.iniPath = value;
            }
        }

        #endregion
    }