Auf das Thema antworten  [ 1 Beitrag ] 
Speichern als INI-Datei 
Autor Nachricht
Administrator
Benutzeravatar

Registriert: Sa 15. Dez 2012, 19:15
Beiträge: 137
Wohnort: Karlsruhe
Mit Zitat antworten
Hallo Leute!

Manchmal ist es sinnvoll die Einstellungen eines Programmes in Klartext zu speichern, damit der Benutzer sie bei Bedarf manuell ändern kann. Gerade Einstellungen die das Startverhalten des Programmes beeinflussen und man somit durch eine Änderung ein nicht mehr startendes Programm wieder zum Laufen bringen kann.

Konkret ging es um die Einstellungen für das Update-Programm von TaDuMa. Dafür habe ich mich zwar für eine INI-Datei entschieden, wollte aber dann doch eine eigene, universelle Lösung dann entwickeln und schrieb die BlockTree-Bibliothek. Denn die fixe Implementierung meiner INI-Datei hat mir dann doch nicht so gefallen.

Code:
 
using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
 
namespace TacticalDungeonMaster
{
    public static partial class Update
    {
        private static class Settings
        {
            private static readonly string SettingFile = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) +
                "\\magonyORG\\Tactical Dungeon Master\\Alpha\\UpdateSettings.ini";
 
            static Settings()
            {
                string dir = Path.GetDirectoryName(SettingFile);
                if (!Directory.Exists(dir)) Directory.CreateDirectory(dir);
                Load();
            }
 
            /// <summary>
            /// Check for downloads on start up of main program
            /// </summary>
            internal static bool CheckForUpdates { get; set; }
            /// <summary>
            /// Initialize update automatically on main program
            /// </summary>
            internal static bool AutoUpdate { get; set; }
 
            /// <summary>
            /// Which packets should be downloaded?
            /// </summary>
            internal static List<string> Packets { get; set; }
            /// <summary>
            /// Start download automatically
            /// </summary>
            internal static bool AutoDownload { get; set; }
            /// <summary>
            /// Start main program after update is complete
            /// </summary>
            internal static bool AutoStart { get; set; }
 
            internal static void Reset()
            {
                CheckForUpdates = false;
                AutoUpdate = false;
                Packets = new List<string>(); Packets.Add("A");
                AutoDownload = true;
                AutoStart = false;
            }
            internal static void Load()
            {
                if (!File.Exists(SettingFile)) { Reset(); Save(); }
                else
                {
                    bool mySektion = false;
                    foreach (string line in File.ReadAllLines(SettingFile, Encoding.UTF8))
                    {
                        if (line.StartsWith(";")) continue;
                        if (line.StartsWith("[")) mySektion = (line == "[Update]");
                        if (!mySektion) continue;
 
                        string[] val = line.Split('=');
                        if (val.Length != 2) continue;
                        switch (val[0].ToLower())
                        {
                            case "checkforupdates": CheckForUpdates = (val[1] == "1"); break;
                            case "autoupdate": AutoUpdate = (val[1] == "1"); break;
                            case "packets": Packets = new List<string>(val[1].Split(' ')); break;
                            case "autodownload": AutoDownload = (val[1] == "1"); break;
                            case "autostart": AutoStart = (val[1] == "1"); break;
                        }
                    }
                }
            }
            internal static void Save()
            {
                List<string> output = new List<string>(11);
                output.Add("[Update]");
                output.Add("; Check for downloads on start up of main program (Not active yet)");
                output.Add("CheckForUpdates=" + (CheckForUpdates ? "1" : "0"));
                output.Add("; Initialize update automatically on main program");
                output.Add("AutoUpdate=" + (AutoUpdate ? "1" : "0"));
                output.Add("; Which packets should be downloaded?");
                output.Add("Packets=" + string.Join(" ", Packets.ToArray()));
                output.Add("; Start download automatically");
                output.Add("AutoDownload=" + (AutoDownload ? "1" : "0"));
                output.Add("; Start main program after update is complete");
                output.Add("AutoStart=" + (AutoStart ? "1" : "0"));
 
                File.WriteAllLines(SettingFile, output, Encoding.UTF8);
            }
        }
    }
}
 


Auf die Einstellungen kann ich im Code über die statischen Member der statischen Klasse Settings zugreifen. Dazu definiere ich zunächst den Dateipfad in der die Einstellungen gespeichert werden sollen. Zwar ist es eigentlich schöner diese Datei im Programmordner zu speichern, aber um Dateien im Programmordner ändern zu können, muss die Anwendung Administrationsrechte haben. Das ist sehr unpraktisch. Und das Speichern von Einstellungen unter den Eigenen Dateien des Benutzers geht mir wahnsinnig auf die Nerven. Die Programme versauen einem jegliche Ordnung in dem Ordner.

Im statischen Konstruktor sorge ich dafür, dass der Ordner, indem ich die Datei speichern möchte, existiert und lade sie anschließend. Natürlich muss ich in Load() dann darauf achten, dass die Datei evtl. noch überhaupt nicht existiert.

Es folgen die Einstellungen, die ich in der Datei speichern möchte, als statische Felder. Dann die Methode Reset(). Diese Initiiert alle Werte und kann sie gleichzeitig auch zurücksetzen.

Load()
Wie bereits erwähnt, muss ich auch damit rechnen, dass die Datei noch überhaupt nicht existiert, wenn ich versuche sie zu laden. In diesem Fall muss ich zunächst die Werte initiieren und dann die Datei speichern. Ansonsten geht es ans Auslesend er Datei.

Zunächst deklariere ich einen Boolean mySektion und stelle ihn auf false. Da die Datei grundsätzlich auch mehr als nur die Einstellungen für meine Updates speichern könnte (siehe Wiki) muss ich zunächst die Sektion suchen, die für die Anwendung gedacht ist: [Update].

In der nachfolgenden Schleife gehe ich dann alle Zeilen durch. Sollte die Zeile mit einem Semikolon beginnen, dann handelt es sich um einen Kommentar und die Zeile wird übersprungen. Wenn die Zeile mit eckigen Klammern beginnen, dann startet eine neue Sektion und ich muss feststellen, ob es sich dabei um meine handelt. Ist sie es nicht, wird diese Zeile ebenfalls übersprungen.

Die Schlüssel und Werte werden durch einem = voneinander getrennt. Also muss ich die Zeile aufteilen. Sollten dabei nicht genau zwei Teile entstehen, dann ist irgendwas schief gelaufen und ich muss die Zeile überspringen. Ansonsten ordne ich den Feldern entsprechend den schlüsseln ihre Werte zu. Zähneknirschend halte ich mich auch an die Regel, dass die Groß-/Kleinschreibung nicht beachtet wird.

Save()
Durch diese Lösung verhindere ich, dass es die Datei auch für andere Einstellungen verwendbar wird. Das ist nicht gerade schön aber praktikabel. Der Liste output werden die jeweiligen Zeilen für die Ausgabe hinzugefügt. Die Sektion, die Kommentare und die Schlüssel mit ihren Werten. Zum Schluss wird die Datei mit UTF8 gespeichert. Dieses Encoding ist wichtig!

Das Ergebnis sieht dann so aus:
Code:
 
[Update]
; Check for downloads on start up of main program (Not active yet)
CheckForUpdates=0
; Initialize update automatically on main program
AutoUpdate=0
; Which packets should be downloaded?
Packets=A
; Start download automatically
AutoDownload=1
; Start main program after update is complete
AutoStart=0
 



Schöne Grüße,
Magony

_________________
Bei Fragen, Lob, Kritik, Vorschläge, hilfreiche Hinweise oder Alternativvorschläge: Beitrag, neues Thema oder PN.
Für Dinge die diskutiert werden sollten, bitte neues Thema im jeweiligen Forum.
Wenn du nicht weißt wohin: Forum Unsortiert.


Mi 14. Mai 2014, 09:18
Diesen Beitrag melden
Profil Website besuchen
Beiträge der letzten Zeit anzeigen:  Sortiere nach  
Auf das Thema antworten   [ 1 Beitrag ] 

Wer ist online?

Mitglieder in diesem Forum: 0 Mitglieder und 1 Gast


Du darfst neue Themen in diesem Forum erstellen.
Du darfst Antworten zu Themen in diesem Forum erstellen.
Du darfst deine Beiträge in diesem Forum nicht ändern.
Du darfst deine Beiträge in diesem Forum nicht löschen.
Du darfst keine Dateianhänge in diesem Forum erstellen.

Suche nach:
Gehe zu:  
cron
Powered by phpBB® Forum Software © phpBB Group
Designed by ST Software
Deutsche Übersetzung durch phpBB.de

Impressum