Laden...

[gelöst] IniFile-Klasse aus Internet funktioniert nicht ganz.. [==> BOM in Ini-Datei stört]

Erstellt von JustShinigami vor 9 Jahren Letzter Beitrag vor 9 Jahren 2.979 Views
J
JustShinigami Themenstarter:in
3 Beiträge seit 2014
vor 9 Jahren
[gelöst] IniFile-Klasse aus Internet funktioniert nicht ganz.. [==> BOM in Ini-Datei stört]

Hallo liebe Community,
erst einmal ein Hallo an alle, da ich hier neu bin.

Aber nun zum Thema: Ich habe eine IniFile-Klasse anhand eines Internetbeitrages erstellt und leicht angepasst. An sich funktioniert diese Klasse auch wunderbar, allerdings funktionert sie dann nicht mehr, sobald ich weitere Instanzen erstelle.

Hier die IniFile-Klasse

using System.IO;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Text;

namespace Shigami.Framework.Configuration
{
    public class IniFile
    {
        string Path;
        string EXE = Assembly.GetCallingAssembly().GetName().Name;

        [DllImport("kernel32")]
        private static extern long WritePrivateProfileString(string Section, string Key, string Value, string FilePath);

        [DllImport("kernel32")]
        private static extern int GetPrivateProfileString(string Section, string Key, string Default, StringBuilder RetVal, int Size, string FilePath);

        public IniFile(string IniPath = null)
        {
            this.Path = new FileInfo(IniPath ?? EXE + ".ini").FullName;
            if (!File.Exists(Path))
                this.CreateFile();
        }

        public void CreateFile()
        {
            File.Create(this.Path);
        }

        public string Read(string Key, string Section = null)
        {
            var RetVal = new StringBuilder(255);
            IniFile.GetPrivateProfileString(Section ?? EXE, Key, "", RetVal, 255, Path);
            return RetVal.ToString();
        }

        public void Write(string Key, string Value, string Section = null)
        {
            IniFile.WritePrivateProfileString(Section ?? EXE, Key, Value, Path);
        }

        public void DeleteKey(string Key, string Section = null)
        {
            Write(Key, null, Section ?? EXE);
        }

        public void DeleteSection(string Section = null)
        {
            Write(null, null, Section ?? EXE);
        }

        public bool KeyExists(string Key, string Section = null)
        {
            return Read(Key, Section).Length > 0;
        }
    }
}

Der betroffene Codeausschnitt:

private void PostInitComponents()
{
    IniFile Configuration = new IniFile(); //Hier ist die erste Instanz, läuft einwandfrei.
    this.Cursor = new Cursor(Program.LoadCursorFromFile("res\\LoL_ingame_default.cur"));
    this.Size = new Size(Int32.Parse(Configuration.Read("wndx", "GENERAL")), Int32.Parse(Configuration.Read("wndy", "GENERAL")));
    IniFile Language = new IniFile(String.Format("lang\\{0}.ini", Configuration.Read("lang", "GENERAL"))); //Hier ist die 2. Instanz, alle Felder werden nicht gefüllt, es kommt immer "" zurück
    this.MenuBarFile.Text = Language.Read("01", "WINDOW");
    this.MenuBarFile_Open.Text = Language.Read("01_1", "WINDOW");
    this.MenuBarFile_Save.Text = Language.Read("01_2", "WINDOW");
    this.MenuBarFile_Exit.Text = Language.Read("01_3", "WINDOW");
    this.MenuBarOptions.Text = Language.Read("02", "WINDOW");
    this.MenuBarOptions_Language.Text = Language.Read("02_1", "WINDOW");
    this.MainTabStatusValues.Text = Language.Read("03", "WINDOW");
    this.LabelChampion.Text = Language.Read("03_1", "WINDOW");
    this.MainTabItems.Text = Language.Read("04", "WINDOW");
    this.MainTabRunes.Text = Language.Read("05", "WINDOW");
    this.MainTabMasteries.Text = Language.Read("06", "WINDOW");
}

Hier sind die Standart INI und die Sprachdatei (INI).

[GENERAL]
version=1.418.0
patch=4.18
lang=DE
wndx=790
wndy=540
[WINDOW]
01=Datei
01_1=Öffnen
01_2=Speichern
01_3=Schließen
02=Optionen
02_1=Sprache
03=Statuswerte
03_1=Champion
04=Gegenstände
05=Runen
06=Meisterschaften

Ich hatte anfangs den Verdacht, dass man in INIs keine Zahlen als Variablennamen vergeben kann, aber auch wenn ich die Variablennamen zu richtigen Variablennamen ändere, funktioniert es nicht.

Kennt sich einer damit aus?

AKTUALISIERUNG:
Nach einigen Testläufen habe ich herausgefunden, dass es schon mal nicht an mehreren Instanzen liegt, sondern eher an der Funktion selbst oder den Dateien.

Gruß,
JustShinigami

J
JustShinigami Themenstarter:in
3 Beiträge seit 2014
vor 9 Jahren
Gelöst!

Welch banaler Grund, warum es nicht funktionierte.
Das Problem lag an den INI Files selbst. Denn nach merfachen Tests und Eigenschaftsvergleichen fiel mir auf, dass die funktionierende INI die Codierung "UTF8 ohne BOM" und die nicht funktionierenden INIs "UTF8" haben. Nach Änderung der Codierung funktioniert nun alles.
Damit ist das Thema auch geschlossen, allerdings würde es mich interessieren, warum Windows "UTF8" Formate bei INIs nicht lesen kann.

Gruß,
JustShinigami

F
10.010 Beiträge seit 2004
vor 9 Jahren

Weil das Ini Format seit gefühlten 1000 Jahren nicht mehr benutzt werden sollte.
Warum hat MS denn (XML) Settings eingeführt?

Eigentlich benutzt mal unter .NET auch nicht diese API Funktionen, da es hier schon sehr gute ( und auch z.b. für XML einsetzbare ) Biblioteken gibt.

Und für Übersetzungen benutzt man sie schon ganz bestimmt nicht, das macht man in Dotnet ganz anders.

Das sieht mir alles nach einer schlechten Transformation eines VB6 Programs nach .NET aus.

Evtl solltest du mal die wirklichen Grundlagen zu .NET erarbeiten.

T
2.224 Beiträge seit 2008
vor 9 Jahren

Außerdem nutzt du die Ini Dateien wohl auch für Übersetzungen.
Dafür sind Ini Dateien nicht gedacht.

Für Configs -> App.config
Für Übersetzungen .resx Dateien

Alles andere ist aus .Net Sicht meistens Fummelei und sehr unsauber.
Ini Dateien haben auch das Problem, dass nicht kar ist welches Encoding verwendet wird.
Bei den Xml Dateien wird diese Info direkt im Xml Header angegeben.

Ob man Ini als Dateiformat noch verwendet oder nicht ist eine persönliche Vorliebe des Entwicklers.
Unter .Net selbst macht es keiner mehr da es mit den Xml basierten Dateien saubere Lösungen gibt.

Aber gerade diese gehören noch zu den Basics.
Für mehr Infos solltest du googeln.

T-Virus

Developer, Developer, Developer, Developer....

99 little bugs in the code, 99 little bugs. Take one down, patch it around, 117 little bugs in the code.

49.485 Beiträge seit 2005
vor 9 Jahren

Hallo zusammen,

die Anmerkungen sind für neue Projekte wichtig und richtig, helfen aber nichts, wenn es darum geht, vorhandene ini-Dateien (z.B. von alten und/oder fremden Programmen) einzulesen.

Hallo JustShinigami,

trotzdem kann es natürlich sein, dass die zugehörigen Windows-API-Funktionen deshalb nicht mehr gepflegt werden und deshalb nicht mit (im Vergleich zum Entwicklungszeitpunkt des APIs) neueren "Features" wie BOMs umgehen können.

Im Zweifel muss man das BOM rausschmeißen, wie du es gemacht hast, oder sich eine der vielen Implementierungen im Netz suchen, die damit umgehen können.

herbivore

J
JustShinigami Themenstarter:in
3 Beiträge seit 2014
vor 9 Jahren

Ob man Ini als Dateiformat noch verwendet oder nicht ist eine persönliche Vorliebe des Entwicklers.

So in etwa. Ich verstehe eure Zweifel und habe auch nun diese INI-Klasse beiseite geschafft. Ich werde nun an einer eigenen Klasse arbeiten, die Encoding-unabhängig ist.

Warum ich App.config und für Übersetzungen resx nicht nutze, hat einen ganz simplen, aber kräftigen Grund: Aktualisierungen;
Wenn die Nutzer meines Programms nach jeder noch so kleinen Änderung die gesamte Exe neu downloaden müsste, wäre das viel zu viel.
Warum dann INIs und keine XML Settings? Weil ich sehr oft Daten manuell ändern werde für das Programm, und ich das INI-Format deutlich angenehmer finde als das der XML Settings.

Und ihr habt auch Recht in Punkto "Inis sind keine Sprachdateien". Dies ist nur eine temporäre Lösung, bis ich ein Format für .lang-dateien erarbeitet habe.

PS:

Das sieht mir alles nach einer schlechten Transformation eines VB6 Programs nach .NET aus.

Das mag vielleicht so aussehen, allerdings habe ich mit VB6 wenig am Hut. Und wenn ich mich recht entsinne, ist VB doch auch Teil von .NET oder irre ich mich da? 😃

Btw: Hätte jemand eine Idee, was ich für Übersetzungen noch nutzen könnte? Ich hatte mal an eine Datenbank gedacht, muss mich da aber noch ein wenig einarbeiten.

PS: Danke herbivore für deine nachträgliche Aufklärung. Der Grund für mich, diese API Funktionen zu nutzen war ganz einfach, dass ich das Rad (INIs lesen/schreiben) nicht neu erfinden wollte und in nahezu allen Internetbeiträgen auf derartige Klassen verweisen. Deshalb ging ich auch davon aus, dass dies eine legitime Lösung wäre.

Ansonsten ein Danke an alle, die hier ihren Betrag niedergelassen haben, es bringt mich in meinem Projekt und sicher auch den einen oder anderen Leser weiter.

Gruß, JustShinigami

F
10.010 Beiträge seit 2004
vor 9 Jahren

Wenn die Nutzer meines Programms nach jeder noch so kleinen Änderung die gesamte Exe neu downloaden müsste, wäre das viel zu viel.

Dann mache eben keine Monolitische Exe.

Dies ist nur eine temporäre Lösung, bis ich ein Format für .lang-dateien erarbeitet habe.

Auch das gibt es schon lange, muss man nicht selber machen .

Hätte jemand eine Idee, was ich für Übersetzungen noch nutzen könnte? Ich hatte mal an eine Datenbank gedacht, muss mich da aber noch ein wenig einarbeiten.

Da du nicht der erste bist der sowas macht, www.codeplex.com und www.codeproject.com haben zig verschiedene Lösungen dafür, und alle Open Source ( liznez trotzdem beachten ).
Meist wird es zusammen mit Localization oder i18N beschrieben.

Und wenn ich mich recht entsinne, ist VB doch auch Teil von .NET oder irre ich mich da? 😃

VB6 war lange vor Dotnet da und VB.NET hat nur ein bisschen Syntax mit VB6 gemein, und eben die Programmierer.

4.221 Beiträge seit 2005
vor 9 Jahren

Offtopic:

Den Spruch muss ich mir merken...

VB6 war lange vor Dotnet da und VB.NET hat nur ein bisschen Syntax mit VB6 gemein, und eben die Programmierer.

PS: Man kann auch mit VB.NET mit einem sauberen Stil gute Programme entwickeln... wie auch mit C# friemeln und schlechten Code schreiben... aber die Tendenz ist schon da ... (VB=Viele Bastler).

Gruss Programmierhans

Früher war ich unentschlossen, heute bin ich mir da nicht mehr so sicher...

T
2.224 Beiträge seit 2008
vor 9 Jahren

@JustShinigami
Ich verstehe dein Argument gegen die Resx/App.config nicht wirklich.
Du musst nicht die gesamte Exe neu laden, wenn du Updates bereit stellst.
Dann musst du nur die Texte/Einträge in der Xml Datei anpassen.

Wenn du aber neue Eigenschaften in deinem Programm ausliest bzw. verwendest musst du auch bei Ini Dateien die Exe updaten.
Deshalb macht das Argument keinen Sinn.

Mach es lieber über die App.config und Resx Dateien, dann bist du eigentlich sauber und hast das ganze Encoding auch nicht als Problem.
Die App.config und die Resx Pflege kannst du auch direkt in VS machen was sehr einfach und angenehm ist.
Ist einfacher als in irgendwelchen Dateien per Editor zu fummeln.

T-Virus

Developer, Developer, Developer, Developer....

99 little bugs in the code, 99 little bugs. Take one down, patch it around, 117 little bugs in the code.