Name des Programms
IniLib
Beschreibung
Als Nachfolger der IniLib 1.0 übernimmt diese Programmbibliothek das Arbeiten mit Initialisierungsdateien (.ini-Dateien). Neben einfachen Funktionalitäten, wie das bearbeiten der einzelnen Strukturelemente einer Initialisierungsdatei wird auch ein gepuffertes Laden von Dateien, Streams und anderen Datenquellen (z.B. Strings) geboten. Diese können bei Bedarf ergänzt werden. Ferner können Dateitypen, die ähnlich aufgebaut sind, wie Initialisierungsdateien, bearbeitet werden (siehe Programmanleitung).
In der IniLib 2.0 wurde das Konzept der alten IniLib komplett neu überarbeitet. Die alte IniLib finden Sie hier. Allerdings empfehle ich, diese aufgrund einiger Fehler nicht weiter zu verwenden.
Verwendete Programmiersprache
Visual Basic .NET (Entwicklungsumgebung: Visual Basic 2010 Express)
Systemanforderungen
.NET Framework 2.0
Download
IniLib 2.3.zip(Komprimierte Datengröße: 32,4 KB, Datengröße: 142 KB)
- IniLib Programmbibliothek (IniLibCore.dll, Dateigröße: 58,5 KB)
- Dokumentation englisch (IniLibCore.xml, Dateigröße: 83,5 KB)
IniLibCore Sourcecode.zip(Komprimierte Datengröße: 41,2 KB, Datengröße: 272 KB)
- IniLib Sourcecode (Mehrere Dateien, Datengröße 272 KB)
Hinweise
- Schlüssel-Wert-Paare (bzw. Key-Value pairs) haben im Englischen eigentlich die Bezeichnung "Property"
Weitergabe
Dieses Produkt und sämtliche mitgelieferte oder optionale Komponenten dürfen nicht durch andere unter deren Namen zum Download angeboten werden. Die Verbreitung der IniLib mit Programmen, die auf ihrem Quellcode (d.h. die Programmbibliothek wird nicht mitgeliefert) basieren, ist gestattet, hat aber für den jeweiligen Anwendungsentwickler zur Folge, dass der Name des Entwicklers der IniLib offensichtlich zu machen ist. Hierbei soll die Quelle (vb-paradise.de), der Entwicklername (~blaze~) und der Produktname (IniLib) genannt werden. Eine Namensnennung ist nicht erforderlich, wenn die Programmbibliothek dem Programm beiliegt.
Dekompilieren des Programms oder jeglicher mitgelieferter oder optionaler Komponenten, deren Sourcecode nicht zum Download geboten und explizit als solcher gekennzeichnet wurde, ist strikt verboten und wird zur Anzeige gebracht.
Inhalt
Inhaltsverzeichnis
1. Management von Initialisierungsdateien
1.1 Initialisierungsdateien, Sektionen und Schlüssel-Wert-Paare
1.2 Laden und Speichern von Initialisierungsdaten
1.3 Konfigurationsmöglichkeiten
1.4 Leerzeilen und Kommentarzeilen
1.5 Informationen zur Auswertung von Initialisierungsdateien
1.6 Serialisierung mithilfe der IniFileSerializer-Klasse
2. Codeschnippsel
2.1 Laden, Verändern und Speichern von Einstellungen
2.2 Ausgabe in Xml-Dokumenten unter Verwendung der System.Xml-Frameworkkomponente
[expander=Anleitung zur Verwendung]
1. Management von Initialisierungsdateien
1.1 Initialisierungsdateien, Sektionen und Schlüssel-Wert-Paare
Generell wurde die Bearbeitung von Initialisierungsdaten durch die IniFile-Klasse implementiert. Eine Instanz der IniFile-Klasse erzeugen Sie wie folgt:
Optional können Sie noch einige Parameter übergeben, die das Verhalten der Klasse und deren Funktionalität modifizieren. So können Sie bereits im Konstruktor eine Datei laden. Dies erzielt die gleiche Wirkung, wie ein Laden mithilfe der LoadFile(String)-Methode.
Die IniFile-Klasse unterstützt neben Dateien auch Streams und Strings und kann durch von der IniTextReader-Klasse erbende Klassen ergänzt werden. Rufen Sie hierzu eine passende Überladung der LoadStream- oder LoadText-Methode auf (Eine Beschreibung können Sie der Dokumentation entnehmen). Die IniFile-Klasse selbst stellt die oberste Ebene der Initialisierungsdatei dar. Innerhalb von ihr werden Sektionen abgelegt, die wiederum Schlüssel-Wert-Paare enthalten können. Sowohl Sektionsköpfe, als auch Schlüssel-Wert-Paare können mit Kommentaren versehen werden. Sektionen können durch die IniFileSection-Klasse verwaltet werden. Hierbei steht die beinhaltende IniFile-Klasseninstanz bereits bei der Erstellung der Instanz fest. Allerdings sind sie zu diesem Zeitpunkt noch nicht Teil des Inhalts, weshalb Sie sie dazu noch der durch die Sections-Eigenschaft der IniFile-Instanz gebotenen Auflistung hinzufügen müssen. Dies geschieht wie folgt:
Neben dem oben verwendeten Konstruktor, der eine Instanz der IniSection-Klasse mit dem Sektionsnamen (Section name) "mySection" erzeugt, gibt es noch Überladungen für Sektionen, die einen Kommentar (Comment) oder Schlüssel-Wert-Paare enthalten. Auf den Sektionsnamen können Sie über die SectionName-Eigenschaft der IniSection-Klasseninstanz zugreifen, auf den Kommentar über die Comment-Eigenschaft. Schlüssel-Wert-Paare können Sie hinzufügen, indem Sie der durch die KeyValues-Eigenschaft gebotenen Auflistung Instanzen der IniFileKeyValuePair-Klasse hinzufügen. Für die Instanzierung der IniFileKeyValuePair-Klasse gibt es jeweilige Konstruktoren, die den Schlüssel (Key), den Wert (Value) oder den Kommentar (Comment) festlegen. Auf diese Werte kann durch die gleich heißenden Eigenschaften zugegriffen werden. Außerdem kann eine Instanz von einer bereits bestehenden Instanz der IniKeyValuePairDescription-Klasse erzeugt werden. Diese Klasse stellt eine Basis für andere Schlüssel-Wert-Paare dar, die nicht durch diese Programmbibliothek verwaltet werden. Auch IniFileKeyValuePair erbt von dieser Klasse. Schlüssel-Wert-Paare können nur einer einzigen Sektion hinzugefügt werden, dieser aber unter Umständen mehrfach (siehe 1.3 Konfigurationsmöglichkeiten).
Folgendes Codebeispiel fügt der im obigen Code erzeugten Sektion eine neue Instanz der IniFileKeyValuePair-Klassed hinzu:
Die Verwaltung der Auflistungen von Sektionen in IniFile-Klasseninstanzen und Schlüssel-Wert-Paaren in IniFileSection-Klasseninstanzen erfolgen gleich, wie in anderen Auflistungen, die die IList(Of T)-Schnittstelle implementieren. So können Sie mit Add Einträge hinzufügen und mit Remove entfernen. Mit IndexOf können Sie den Index eines hinzugefügten Eintrags ermitteln und mit der Item-Eigenschaft auf den Wert am jeweiligen Index zugreifen. Mit Contains überprüfen Sie, ob der Wert in der Auflistung enthalten ist.
1.2 Laden und Speichern von Initialisierungsdaten
Es gibt viele mögliche Quellen, aus denen Sie Initialisierungsdateien laden könnten. So wurde in der IniFile-Klasse die Möglichkeit implementiert, Daten aus Streams oder aus von Ihnen programmierten Operationen zu erstellen. Die folgenden Methoden können Sie verwenden, um Daten zu laden:
- LoadFile lädt Dateien
- LoadStream lädt Daten aus Streams
- LoadText lädt Daten aus Strings
- Load lädt Daten aus von Ihnen programmierten Quellen
Der Parameter keepPrevious gibt hierbei an, ob der vorher geladene Inhalt weiter verfügbar sein soll oder ob die geladene Initialisierungsdatei geleert werden soll. Standardmäßig werden die Daten beibehalten. Der Parameter encoding gibt die Zeichencodierung an, in der die Daten vorliegen. Als Standardwert wird die Zeichencodierung verwendet, die die System.Text.Encoding.Default-Eigenschaft angibt. Für Daten, die als Strings vorliegen wird außerdem die Möglichkeit angeboten, die Größe des in der Methode verwendeten Stringpuffers direkt anzugeben. Diesen Parameter sollten Sie verwenden, wenn Sie wissen, dass Schlüssel, Werte, Kommentare oder Sektionsnamen eine bestimmte Länge nicht überschreiten. Ansonsten muss bei einer unzureichenden Puffergröße weiterer Speicher allokiert werden, was sich performancelastig auswirkt.
Die folgenden Methoden können Sie verwenden, um Daten zu speichern:
- ToString gibt die vollständie Initialisierungsdatei als String zurück
- Save(String) und Save(String, Encoding) können Sie verwenden, um die Initialisierungsdatei in eine Datei zu speichern
- Save(Stream) und Save(Stream, Encoding) können Sie verwenden, um die Initialisierungsdatei in einen Stream zu speichern
- Save(IniTextWriter) können Sie verwenden, um die Initialisierungsdatei in ein von Ihnen programmiertes Ziel zu speichern
Der encoding-Parameter steht für die zu verwendende Zeichencodierung mit dem Standardwert, der von der System.Text.Encoding.Default-Eigenschaft zurückgegeben wird.
Die abstrakten IniTextReader- und IniTextWriter-Klassen wurden nur zu einer möglichen Steigerung der Effizienz in dieser Art implementiert. Da verschiedene Datenquellen nicht auf Streams optimiert sind oder auf sonst ausgeführte, effizienzlastige Konversionen zugreifen müssen, die wieder zum gleichen Resultat führen, wurden die beiden Klassen so angelegt, dass nur die grundlegenden Methoden überschrieben werden müssen. Außerdem können weitere Methoden und Eigenschaften überschrieben werden, die für Ihren Fall optimierter programmierbar sind. Zudem können Sie das Verhalten in bestimmten Fällen verändern oder andere Dateitypen implementieren, deren Struktur ähnlich der von Initialisierungsdateien ist. Letzteres können Sie aber auch eingeschränkter durch ein Überschreiben der IniFile-Klasse erreichen. Das Lesen und Schreiben von Streams wurde auch in dieser Art implementiert. Weitere Informationen können Sie den Beschreibungen der jeweiligen Mitglieder entnehmen.
1.3 Konfigurationsmöglichkeiten
Durch das Übergeben von IniLib.IniFileFlags-Flaggen an den Konstruktor der IniFile-Klasse können Sie das Verhalten der IniFile und von IniFileSections verändern. In normalen Initialisierungsdateien ist es beispielsweise nicht gestattet, dass mehrere Sektionen den gleichen Namen oder mehrere Schlüssel-Wert-Paare innerhalb einer Sektion den gleichen Schlüssel haben. Durch das Übergeben der IniLib.IniFileFlags.SupportsSectionNameRepetition-Flagge können Sie die Wiederholung von Sektionsnamen innerhalb einer Datei und der IniLib.IniFileFlags.SupportsKeyValuePairKeyRepetition-Flagge die Wiederholung von Schlüssel-Wert-Paaren innerhalb einer Sektion erlauben. Die IniLib.IniFileFlags.CaseInsensitive-Flagge gibt an, dass die Groß-und Kleinschreibung bei der Auswahl von Sektionen und Schlüsseln nicht berücksichtigt werden soll. Beim Vergleichen von Strings wird bei einer Übergabe der Flagge ein kulturunabhängiger (invarianter) Vergleich durchgeführt.
Neben den Flaggen können Sie auch eine Klasse von der IniFile-Klasse ableiten. Hierbei können Sie das Trennzeichen für Schlüssel-Wert-Paare oder auch das Kommentarzeichen festlegen.
1.4 Leerzeilen und Kommentarzeilen
Initialisierungsdateien können auch Leerzeilen oder Kommentarzeilen enthalten. Diese Spezialfälle wurden durch spezielle Werte von Sektionsnamen, Schlüsseln und Kommentaren umgesetzt:
- Ist ein Sektionsname Nothing (Null) oder leer, so ist er nicht sichtbar
- Ist ein Sekitionskommentar nicht Nothing (Null), so ist er sichtbar
- Ist ein Key Nothing (Null) oder leer, so ist das Schlüssel-Wert-Paar nicht sichtbar
- Ist der Kommentar eines Schlüssel-Wert-Paars nicht Nothing (Null), so ist er sichtbar
Innerhalb von Sektionen, deren Sektionsname nicht sichtbar ist, dürfen nur Kommentare und Leerzeichen enthalten sein. Die Werte von Schlüssel-Wert-Paaren sind nicht sichtbar, wenn der Schlüssel nicht sichtbar ist.
Innerhalb einer Auflistung werden Sektionen ohne Namen ebenfalls mit Nothing (Null) bzw. einem leeren String angesprochen. Dieser Wert muss aber mit dem Sektionsnamen übereinstimmen (Nothing (Null) spricht einen Sektionsnamen mit Nothing (Null), ein leerer String einen Sektionsnamen, der leer ist, an).
1.5 Informationen zur Auswertung von Initialisierungsdateien
Wie aus Kapitel 1.4 hervorgeht, können Leerzeilen und Kommentarzeilen auf unterschiedliche Weise erstellt werden. So können Sie zur Laufzeit eine Sektion, deren Sektionsname nicht sichtbar ist, auf eine andere Sektion folgen lassen. Diese Kombination ist zulässig und wird auch korrekt gespeichert. Allerdings ist das Ergebnis nach dem Laden anders, als beim Speichern, da Kommentarzeilen als Teil der vorherigen Sektion angesehen wird. Wenn eine Initialisierungsdatei mit einer Kopfzeile beginnt, wird eine neue Sektion angelegt. Alle nachfolgenden Kommentarzeilen werden dieser Sektion angefügt. Daher wird empfohlen, dass Sie bereits beim Speichern diese Strukturierung berücksichtigen.
Da es verschiedene Zeilenumsprungskombinationen in unterschiedlichen Systemen gibt, wurde die Stringinterpretation an sie angepasst. Sowohl Carriage Return (Cr, Chr(13)), als auch Line feed (Lf, Chr(10)) werden als Zeilenumsprung behandelt. Aber auch CrLf und LfCr werden als ein einziger Zeilenumsprung interpretiert.
Ferner werden Sektionsnamen, die mit Leerzeichen beginnen oder enden, nicht untestützt; wenn Leerzeichen vor der öffnenden Klammer ('[') oder nach der schießenden Klammer (']') stehen, werden diese übersprungen. Leerzeichen vor und nach Schlüsseln und Werten werden übersprungen. Kommentare bleiben vollständig erhalten.
1.6 Serialisierung mithilfe der IniFileSerializer-Klasse
Sie können seit der Version 2.1 Objekte mithilfe der IniFileSerializer-Klasse der IniLib auch serialisieren. Hierbei wurde das Konzept der Xml-Serialisierung weitgehend aufgenommen. Zur Anwendung müssen Sie erst eine Instanz der IniFileSerializer-Klasse erzeugen (Dies dient der Kompatibilität mit möglichen späteren Versionen, die eine andere Implementierung anbieten, aber auch der Veränderbarkeit interner vererbter Methoden. Diese wird in den meisten Fällen nicht benötigt und deshalb an dieser Stelle weggelassen). Optional können Sie noch das Trennzeichen für die Mitgliedshierarchie festlegen. Dieses wird verwendet, wenn Werte gespeichert werden, die nicht primitiv, NULL (in Visual Basic Nothing) oder ein String sind und ist bei keiner Angabe ein '.'-Zeichen.
Rufen Sie zur Serialisierung von Objekten die Serialize-Methode mit dem Namen des Objektes, das zu serialisieren ist, dem zu serialisierenden Wert und einer Instanz der IniFile-Klasse auf. Beachten Sie hierbei, dass pro Hierarchieebene eine neue IniFileSection hinzugefügt wird und bestehende Elemente nicht überschrieben werden. Dies ist auch bei der Auswertung von Initialisierungsdateien zu beachten, denn hierbei werden bei mehrfachem Vorkommen immer die ersten Sektionen ausgewählt, deren Sektionsname dem Kriterium entspricht.
Für die Deserialisierung wird die Deserialize-Methode aufgerufen. Als erster Parameter wird der Name des zu serialisierenden Objekts angegeben, als zweiter die das Objekt beschreibende IniFile-Instanz. Die Funktion gibt das deserialisierte Objekt als Objekt zurück.
Namen von Objekten können Sie mithilfe der IsValidObjectName-Methode überprüft werden. Hierbei werden entweder die IniFile-Instanz, Trennzeichen für Schlüssel-Wert-Paare und Kommentare benötigt oder die Standardtrennzeichen verwendet. Beispielsweise können Sie die Namen von Feldern oder Eigenschaften verwenden.
Serialisierte Objekte müssen mit einem System.SerializableAttribute-Attribut versehen werden. Felder und Eigenschaften einer Instanz, bei denen kein NonSerializedAttribute-Attribut angegeben wurde, werden serialisiert, wenn Sie öffentlich und beschreibbar sind. Eigenschaften dürfen außerdem keine Indices haben. Beachten Sie, dass auch Felder und Eigenschaften, für die ein System.ComponentModel.BrowsableAttribute- oder ein System.ComponentModel.EditorBrowsableAttribute-Attribut angegeben wurde, serialisiert werden. Wenn Sie eine eigene Serialisierungsart implementieren möchten, implementieren Sie die ISerializable-Klasse, überschreiben alle angeforderten Methoden und erstellen Sie einen deserialisierenden Konstruktor, der als ersten Parameter die System.Runtime.Serialization.SerializationInfo, aus der Sie die zu serialisierende Daten beziehen können und als zweiten Parameter einen System.Runtime.Serialization.StreamingContext, unter dem die Deserialisierung stattfindet, hat.
2. Codeschnippsel
In den Schnippseln wird ein Import des IniLib-Namensraums vorausgesetzt.
2.1 Laden, Verändern und Speichern von Einstellungen
Das Beispiel behandelt das Laden, verändern und speichern von Initialisierungsdateien.
Im Folgenden Codesegment wird eine IniFile-Klasseninstanz verwendet, um die Position und Größe eines Fensters zu laden. Es ist empfehlenswert, die IniFile-Klasseninstanz innerhalb der Klasse abzulegen, da sie dadurch nicht jedes mal erzeugt werden muss.
* (Effizienz von IndexOf höher, als von Contains): Beim Aufruf von get_Item(String), IndexOf und Contains wird durch die Elemente der Auflistungen durchiteriert und überprüft, ob der Schlüssel übereinstimmt. Bei einer Kombination von get_Item(String) und Contains wird somit zwei mal durch die Schleife gegangen, bei IndexOf nur einmal, was effizienter ist, da die Elemente der Auflistung sequentiell angeordnet sind und sich somit der Zeiger auf das Element der Auflistung aus dem Index berechnen lässt.
Ungültige Werte sollten mit einem Nachrichtenfenster oder einer anderen Fehlerbehandlung gemeldet werden.
Im Folgenden Codesegment werden die Informationen der MainForm-Klasseninstanz verändert und anschließend in die Datei zurückgeschrieben.
2.2 Ausgabe in Xml-Dokumenten unter Verwendung der System.Xml-Frameworkkomponente
Im Code wird ein Import des System.Xml-Namensraums vorausgesetzt.
Log
Version 2.3:
- Werte unterstützen nun auch den '='-Buchstaben (Bug im IniFileSerializer wurde damit behoben, da System.Type.AssemblyQualifiedName ein '=' enthalten kann)
- Fehlverhalten beim Auslesen von Streams auf Systemen mit CrLf- bzw. LfCr-Zeilenumsprüngen behoben, das zu leeren Schlüssel-Wert-Paaren führte
Version 2.2:
- Überarbeitung der IniFileSerializer-Klasse, die nun bereits bestehende Sektionen und Schlüssel-Wert-Paare überschreibt, statt neue anzulegen
Version 2.1:
- IniFileSerializer hinzugefügt (Anwendung siehe Anleitung)
Version 2.0:
- Die IniLib wurde komplett neu erstellt
Ich würde mich über Verbesserungsvorschläge, Anregungen und konstruktive Kritik freuen und werde Fragen gerne beantworten. Vielen Dank für den Download und viel Spaß mit der Entwicklung.
Mit freundlichen Grüßen
~blaze~
Edit by ~blaze~:
Sourcecode wurde verfügbar gemacht
--> *Thema aus dem Showroom verschoben*
IniLib
Beschreibung
Als Nachfolger der IniLib 1.0 übernimmt diese Programmbibliothek das Arbeiten mit Initialisierungsdateien (.ini-Dateien). Neben einfachen Funktionalitäten, wie das bearbeiten der einzelnen Strukturelemente einer Initialisierungsdatei wird auch ein gepuffertes Laden von Dateien, Streams und anderen Datenquellen (z.B. Strings) geboten. Diese können bei Bedarf ergänzt werden. Ferner können Dateitypen, die ähnlich aufgebaut sind, wie Initialisierungsdateien, bearbeitet werden (siehe Programmanleitung).
In der IniLib 2.0 wurde das Konzept der alten IniLib komplett neu überarbeitet. Die alte IniLib finden Sie hier. Allerdings empfehle ich, diese aufgrund einiger Fehler nicht weiter zu verwenden.
Verwendete Programmiersprache
Visual Basic .NET (Entwicklungsumgebung: Visual Basic 2010 Express)
Systemanforderungen
.NET Framework 2.0
Download
IniLib 2.3.zip(Komprimierte Datengröße: 32,4 KB, Datengröße: 142 KB)
- IniLib Programmbibliothek (IniLibCore.dll, Dateigröße: 58,5 KB)
- Dokumentation englisch (IniLibCore.xml, Dateigröße: 83,5 KB)
IniLibCore Sourcecode.zip(Komprimierte Datengröße: 41,2 KB, Datengröße: 272 KB)
- IniLib Sourcecode (Mehrere Dateien, Datengröße 272 KB)
Hinweise
- Schlüssel-Wert-Paare (bzw. Key-Value pairs) haben im Englischen eigentlich die Bezeichnung "Property"
Weitergabe
Dieses Produkt und sämtliche mitgelieferte oder optionale Komponenten dürfen nicht durch andere unter deren Namen zum Download angeboten werden. Die Verbreitung der IniLib mit Programmen, die auf ihrem Quellcode (d.h. die Programmbibliothek wird nicht mitgeliefert) basieren, ist gestattet, hat aber für den jeweiligen Anwendungsentwickler zur Folge, dass der Name des Entwicklers der IniLib offensichtlich zu machen ist. Hierbei soll die Quelle (vb-paradise.de), der Entwicklername (~blaze~) und der Produktname (IniLib) genannt werden. Eine Namensnennung ist nicht erforderlich, wenn die Programmbibliothek dem Programm beiliegt.
Dekompilieren des Programms oder jeglicher mitgelieferter oder optionaler Komponenten, deren Sourcecode nicht zum Download geboten und explizit als solcher gekennzeichnet wurde, ist strikt verboten und wird zur Anzeige gebracht.
Inhaltsverzeichnis
1. Management von Initialisierungsdateien
1.1 Initialisierungsdateien, Sektionen und Schlüssel-Wert-Paare
1.2 Laden und Speichern von Initialisierungsdaten
1.3 Konfigurationsmöglichkeiten
1.4 Leerzeilen und Kommentarzeilen
1.5 Informationen zur Auswertung von Initialisierungsdateien
1.6 Serialisierung mithilfe der IniFileSerializer-Klasse
2. Codeschnippsel
2.1 Laden, Verändern und Speichern von Einstellungen
2.2 Ausgabe in Xml-Dokumenten unter Verwendung der System.Xml-Frameworkkomponente
[expander=Anleitung zur Verwendung]
1. Management von Initialisierungsdateien
1.1 Initialisierungsdateien, Sektionen und Schlüssel-Wert-Paare
Generell wurde die Bearbeitung von Initialisierungsdaten durch die IniFile-Klasse implementiert. Eine Instanz der IniFile-Klasse erzeugen Sie wie folgt:
Optional können Sie noch einige Parameter übergeben, die das Verhalten der Klasse und deren Funktionalität modifizieren. So können Sie bereits im Konstruktor eine Datei laden. Dies erzielt die gleiche Wirkung, wie ein Laden mithilfe der LoadFile(String)-Methode.
Die IniFile-Klasse unterstützt neben Dateien auch Streams und Strings und kann durch von der IniTextReader-Klasse erbende Klassen ergänzt werden. Rufen Sie hierzu eine passende Überladung der LoadStream- oder LoadText-Methode auf (Eine Beschreibung können Sie der Dokumentation entnehmen). Die IniFile-Klasse selbst stellt die oberste Ebene der Initialisierungsdatei dar. Innerhalb von ihr werden Sektionen abgelegt, die wiederum Schlüssel-Wert-Paare enthalten können. Sowohl Sektionsköpfe, als auch Schlüssel-Wert-Paare können mit Kommentaren versehen werden. Sektionen können durch die IniFileSection-Klasse verwaltet werden. Hierbei steht die beinhaltende IniFile-Klasseninstanz bereits bei der Erstellung der Instanz fest. Allerdings sind sie zu diesem Zeitpunkt noch nicht Teil des Inhalts, weshalb Sie sie dazu noch der durch die Sections-Eigenschaft der IniFile-Instanz gebotenen Auflistung hinzufügen müssen. Dies geschieht wie folgt:
Neben dem oben verwendeten Konstruktor, der eine Instanz der IniSection-Klasse mit dem Sektionsnamen (Section name) "mySection" erzeugt, gibt es noch Überladungen für Sektionen, die einen Kommentar (Comment) oder Schlüssel-Wert-Paare enthalten. Auf den Sektionsnamen können Sie über die SectionName-Eigenschaft der IniSection-Klasseninstanz zugreifen, auf den Kommentar über die Comment-Eigenschaft. Schlüssel-Wert-Paare können Sie hinzufügen, indem Sie der durch die KeyValues-Eigenschaft gebotenen Auflistung Instanzen der IniFileKeyValuePair-Klasse hinzufügen. Für die Instanzierung der IniFileKeyValuePair-Klasse gibt es jeweilige Konstruktoren, die den Schlüssel (Key), den Wert (Value) oder den Kommentar (Comment) festlegen. Auf diese Werte kann durch die gleich heißenden Eigenschaften zugegriffen werden. Außerdem kann eine Instanz von einer bereits bestehenden Instanz der IniKeyValuePairDescription-Klasse erzeugt werden. Diese Klasse stellt eine Basis für andere Schlüssel-Wert-Paare dar, die nicht durch diese Programmbibliothek verwaltet werden. Auch IniFileKeyValuePair erbt von dieser Klasse. Schlüssel-Wert-Paare können nur einer einzigen Sektion hinzugefügt werden, dieser aber unter Umständen mehrfach (siehe 1.3 Konfigurationsmöglichkeiten).
Folgendes Codebeispiel fügt der im obigen Code erzeugten Sektion eine neue Instanz der IniFileKeyValuePair-Klassed hinzu:
Die Verwaltung der Auflistungen von Sektionen in IniFile-Klasseninstanzen und Schlüssel-Wert-Paaren in IniFileSection-Klasseninstanzen erfolgen gleich, wie in anderen Auflistungen, die die IList(Of T)-Schnittstelle implementieren. So können Sie mit Add Einträge hinzufügen und mit Remove entfernen. Mit IndexOf können Sie den Index eines hinzugefügten Eintrags ermitteln und mit der Item-Eigenschaft auf den Wert am jeweiligen Index zugreifen. Mit Contains überprüfen Sie, ob der Wert in der Auflistung enthalten ist.
1.2 Laden und Speichern von Initialisierungsdaten
Es gibt viele mögliche Quellen, aus denen Sie Initialisierungsdateien laden könnten. So wurde in der IniFile-Klasse die Möglichkeit implementiert, Daten aus Streams oder aus von Ihnen programmierten Operationen zu erstellen. Die folgenden Methoden können Sie verwenden, um Daten zu laden:
- LoadFile lädt Dateien
- LoadStream lädt Daten aus Streams
- LoadText lädt Daten aus Strings
- Load lädt Daten aus von Ihnen programmierten Quellen
Der Parameter keepPrevious gibt hierbei an, ob der vorher geladene Inhalt weiter verfügbar sein soll oder ob die geladene Initialisierungsdatei geleert werden soll. Standardmäßig werden die Daten beibehalten. Der Parameter encoding gibt die Zeichencodierung an, in der die Daten vorliegen. Als Standardwert wird die Zeichencodierung verwendet, die die System.Text.Encoding.Default-Eigenschaft angibt. Für Daten, die als Strings vorliegen wird außerdem die Möglichkeit angeboten, die Größe des in der Methode verwendeten Stringpuffers direkt anzugeben. Diesen Parameter sollten Sie verwenden, wenn Sie wissen, dass Schlüssel, Werte, Kommentare oder Sektionsnamen eine bestimmte Länge nicht überschreiten. Ansonsten muss bei einer unzureichenden Puffergröße weiterer Speicher allokiert werden, was sich performancelastig auswirkt.
Die folgenden Methoden können Sie verwenden, um Daten zu speichern:
- ToString gibt die vollständie Initialisierungsdatei als String zurück
- Save(String) und Save(String, Encoding) können Sie verwenden, um die Initialisierungsdatei in eine Datei zu speichern
- Save(Stream) und Save(Stream, Encoding) können Sie verwenden, um die Initialisierungsdatei in einen Stream zu speichern
- Save(IniTextWriter) können Sie verwenden, um die Initialisierungsdatei in ein von Ihnen programmiertes Ziel zu speichern
Der encoding-Parameter steht für die zu verwendende Zeichencodierung mit dem Standardwert, der von der System.Text.Encoding.Default-Eigenschaft zurückgegeben wird.
Die abstrakten IniTextReader- und IniTextWriter-Klassen wurden nur zu einer möglichen Steigerung der Effizienz in dieser Art implementiert. Da verschiedene Datenquellen nicht auf Streams optimiert sind oder auf sonst ausgeführte, effizienzlastige Konversionen zugreifen müssen, die wieder zum gleichen Resultat führen, wurden die beiden Klassen so angelegt, dass nur die grundlegenden Methoden überschrieben werden müssen. Außerdem können weitere Methoden und Eigenschaften überschrieben werden, die für Ihren Fall optimierter programmierbar sind. Zudem können Sie das Verhalten in bestimmten Fällen verändern oder andere Dateitypen implementieren, deren Struktur ähnlich der von Initialisierungsdateien ist. Letzteres können Sie aber auch eingeschränkter durch ein Überschreiben der IniFile-Klasse erreichen. Das Lesen und Schreiben von Streams wurde auch in dieser Art implementiert. Weitere Informationen können Sie den Beschreibungen der jeweiligen Mitglieder entnehmen.
1.3 Konfigurationsmöglichkeiten
Durch das Übergeben von IniLib.IniFileFlags-Flaggen an den Konstruktor der IniFile-Klasse können Sie das Verhalten der IniFile und von IniFileSections verändern. In normalen Initialisierungsdateien ist es beispielsweise nicht gestattet, dass mehrere Sektionen den gleichen Namen oder mehrere Schlüssel-Wert-Paare innerhalb einer Sektion den gleichen Schlüssel haben. Durch das Übergeben der IniLib.IniFileFlags.SupportsSectionNameRepetition-Flagge können Sie die Wiederholung von Sektionsnamen innerhalb einer Datei und der IniLib.IniFileFlags.SupportsKeyValuePairKeyRepetition-Flagge die Wiederholung von Schlüssel-Wert-Paaren innerhalb einer Sektion erlauben. Die IniLib.IniFileFlags.CaseInsensitive-Flagge gibt an, dass die Groß-und Kleinschreibung bei der Auswahl von Sektionen und Schlüsseln nicht berücksichtigt werden soll. Beim Vergleichen von Strings wird bei einer Übergabe der Flagge ein kulturunabhängiger (invarianter) Vergleich durchgeführt.
Neben den Flaggen können Sie auch eine Klasse von der IniFile-Klasse ableiten. Hierbei können Sie das Trennzeichen für Schlüssel-Wert-Paare oder auch das Kommentarzeichen festlegen.
1.4 Leerzeilen und Kommentarzeilen
Initialisierungsdateien können auch Leerzeilen oder Kommentarzeilen enthalten. Diese Spezialfälle wurden durch spezielle Werte von Sektionsnamen, Schlüsseln und Kommentaren umgesetzt:
- Ist ein Sektionsname Nothing (Null) oder leer, so ist er nicht sichtbar
- Ist ein Sekitionskommentar nicht Nothing (Null), so ist er sichtbar
- Ist ein Key Nothing (Null) oder leer, so ist das Schlüssel-Wert-Paar nicht sichtbar
- Ist der Kommentar eines Schlüssel-Wert-Paars nicht Nothing (Null), so ist er sichtbar
Innerhalb von Sektionen, deren Sektionsname nicht sichtbar ist, dürfen nur Kommentare und Leerzeichen enthalten sein. Die Werte von Schlüssel-Wert-Paaren sind nicht sichtbar, wenn der Schlüssel nicht sichtbar ist.
Innerhalb einer Auflistung werden Sektionen ohne Namen ebenfalls mit Nothing (Null) bzw. einem leeren String angesprochen. Dieser Wert muss aber mit dem Sektionsnamen übereinstimmen (Nothing (Null) spricht einen Sektionsnamen mit Nothing (Null), ein leerer String einen Sektionsnamen, der leer ist, an).
1.5 Informationen zur Auswertung von Initialisierungsdateien
Wie aus Kapitel 1.4 hervorgeht, können Leerzeilen und Kommentarzeilen auf unterschiedliche Weise erstellt werden. So können Sie zur Laufzeit eine Sektion, deren Sektionsname nicht sichtbar ist, auf eine andere Sektion folgen lassen. Diese Kombination ist zulässig und wird auch korrekt gespeichert. Allerdings ist das Ergebnis nach dem Laden anders, als beim Speichern, da Kommentarzeilen als Teil der vorherigen Sektion angesehen wird. Wenn eine Initialisierungsdatei mit einer Kopfzeile beginnt, wird eine neue Sektion angelegt. Alle nachfolgenden Kommentarzeilen werden dieser Sektion angefügt. Daher wird empfohlen, dass Sie bereits beim Speichern diese Strukturierung berücksichtigen.
Da es verschiedene Zeilenumsprungskombinationen in unterschiedlichen Systemen gibt, wurde die Stringinterpretation an sie angepasst. Sowohl Carriage Return (Cr, Chr(13)), als auch Line feed (Lf, Chr(10)) werden als Zeilenumsprung behandelt. Aber auch CrLf und LfCr werden als ein einziger Zeilenumsprung interpretiert.
Ferner werden Sektionsnamen, die mit Leerzeichen beginnen oder enden, nicht untestützt; wenn Leerzeichen vor der öffnenden Klammer ('[') oder nach der schießenden Klammer (']') stehen, werden diese übersprungen. Leerzeichen vor und nach Schlüsseln und Werten werden übersprungen. Kommentare bleiben vollständig erhalten.
1.6 Serialisierung mithilfe der IniFileSerializer-Klasse
Sie können seit der Version 2.1 Objekte mithilfe der IniFileSerializer-Klasse der IniLib auch serialisieren. Hierbei wurde das Konzept der Xml-Serialisierung weitgehend aufgenommen. Zur Anwendung müssen Sie erst eine Instanz der IniFileSerializer-Klasse erzeugen (Dies dient der Kompatibilität mit möglichen späteren Versionen, die eine andere Implementierung anbieten, aber auch der Veränderbarkeit interner vererbter Methoden. Diese wird in den meisten Fällen nicht benötigt und deshalb an dieser Stelle weggelassen). Optional können Sie noch das Trennzeichen für die Mitgliedshierarchie festlegen. Dieses wird verwendet, wenn Werte gespeichert werden, die nicht primitiv, NULL (in Visual Basic Nothing) oder ein String sind und ist bei keiner Angabe ein '.'-Zeichen.
Rufen Sie zur Serialisierung von Objekten die Serialize-Methode mit dem Namen des Objektes, das zu serialisieren ist, dem zu serialisierenden Wert und einer Instanz der IniFile-Klasse auf. Beachten Sie hierbei, dass pro Hierarchieebene eine neue IniFileSection hinzugefügt wird und bestehende Elemente nicht überschrieben werden. Dies ist auch bei der Auswertung von Initialisierungsdateien zu beachten, denn hierbei werden bei mehrfachem Vorkommen immer die ersten Sektionen ausgewählt, deren Sektionsname dem Kriterium entspricht.
Für die Deserialisierung wird die Deserialize-Methode aufgerufen. Als erster Parameter wird der Name des zu serialisierenden Objekts angegeben, als zweiter die das Objekt beschreibende IniFile-Instanz. Die Funktion gibt das deserialisierte Objekt als Objekt zurück.
Namen von Objekten können Sie mithilfe der IsValidObjectName-Methode überprüft werden. Hierbei werden entweder die IniFile-Instanz, Trennzeichen für Schlüssel-Wert-Paare und Kommentare benötigt oder die Standardtrennzeichen verwendet. Beispielsweise können Sie die Namen von Feldern oder Eigenschaften verwenden.
Serialisierte Objekte müssen mit einem System.SerializableAttribute-Attribut versehen werden. Felder und Eigenschaften einer Instanz, bei denen kein NonSerializedAttribute-Attribut angegeben wurde, werden serialisiert, wenn Sie öffentlich und beschreibbar sind. Eigenschaften dürfen außerdem keine Indices haben. Beachten Sie, dass auch Felder und Eigenschaften, für die ein System.ComponentModel.BrowsableAttribute- oder ein System.ComponentModel.EditorBrowsableAttribute-Attribut angegeben wurde, serialisiert werden. Wenn Sie eine eigene Serialisierungsart implementieren möchten, implementieren Sie die ISerializable-Klasse, überschreiben alle angeforderten Methoden und erstellen Sie einen deserialisierenden Konstruktor, der als ersten Parameter die System.Runtime.Serialization.SerializationInfo, aus der Sie die zu serialisierende Daten beziehen können und als zweiten Parameter einen System.Runtime.Serialization.StreamingContext, unter dem die Deserialisierung stattfindet, hat.
2. Codeschnippsel
In den Schnippseln wird ein Import des IniLib-Namensraums vorausgesetzt.
2.1 Laden, Verändern und Speichern von Einstellungen
Das Beispiel behandelt das Laden, verändern und speichern von Initialisierungsdateien.
Im Folgenden Codesegment wird eine IniFile-Klasseninstanz verwendet, um die Position und Größe eines Fensters zu laden. Es ist empfehlenswert, die IniFile-Klasseninstanz innerhalb der Klasse abzulegen, da sie dadurch nicht jedes mal erzeugt werden muss.
VB.NET-Quellcode
- Dim ifFile As New IniFile() 'Instanz der IniFile-Klasse erzeugen
- ifFile.LoadFile("settings.ini") 'Datei mit Standardzeichencodierung laden
- If ifFile.Sections.Count > 0 Then 'Es sind Sektionen verfuegbar
- If ifFile.Sections.Contains("MainForm") Then
- 'Einstellungen fuer das Hauptfenster laden (Die Instanz der Hauptfenster-Klasse traegt hier den Namen MainForm)
- With ifFile.Sections("MainForm")
- 'Jeweils ueberpruefen, ob die Eigenschaft enthalten ist (IndexOf ist in diesem Fall effizienter, als Contains*)
- Dim index As Integer = .KeyValues.IndexOf("Left")
- If index <> -1 Then
- 'und gegebenenfalls die Eigenschaft setzen
- If Not Integer.TryParse(.KeyValues(index).Value, MainForm.Left) Then
- 'Ungueltiger Wert
- End If
- End If
- index = .KeyValues.IndexOf("Top")
- If index <> -1 Then
- If Not Integer.TryParse(.KeyValues(index).Value, MainForm.Top) Then
- 'Ungueltiger Wert
- End If
- End If
- index = .KeyValues.IndexOf("Width")
- If index <> -1 Then
- If Not Integer.TryParse(.KeyValues(index).Value, MainForm.Width) Then
- 'Ungueltiger Wert
- End If
- End If
- index = .KeyValues.IndexOf("Height")
- If index <> -1 Then
- If Not Integer.TryParse(.KeyValues(index).Value, MainForm.Height) Then
- 'Ungueltiger Wert
- End If
- End If
- End With
- End If
- End If
* (Effizienz von IndexOf höher, als von Contains): Beim Aufruf von get_Item(String), IndexOf und Contains wird durch die Elemente der Auflistungen durchiteriert und überprüft, ob der Schlüssel übereinstimmt. Bei einer Kombination von get_Item(String) und Contains wird somit zwei mal durch die Schleife gegangen, bei IndexOf nur einmal, was effizienter ist, da die Elemente der Auflistung sequentiell angeordnet sind und sich somit der Zeiger auf das Element der Auflistung aus dem Index berechnen lässt.
Ungültige Werte sollten mit einem Nachrichtenfenster oder einer anderen Fehlerbehandlung gemeldet werden.
Im Folgenden Codesegment werden die Informationen der MainForm-Klasseninstanz verändert und anschließend in die Datei zurückgeschrieben.
VB.NET-Quellcode
- Dim ifFile As New IniFile()
- 'MainForm-Sektion ermitteln oder erzeugen
- Dim section As IniFileSection = ifFile.CreateSection("MainForm")
- 'Jeweilige Schluessel-Wert-Paare ermitteln oder erzeugen
- section.CreateKeyValuePair("Left", MainForm.Left.ToString())
- section.CreateKeyValuePair("Top", MainForm.Top.ToString())
- section.CreateKeyValuePair("Width", MainForm.Width.ToString())
- section.CreateKeyValuePair("Height", MainForm.Height.ToString())
- 'Einstellungen speichern
- ifFile.Save("settings.ini")
2.2 Ausgabe in Xml-Dokumenten unter Verwendung der System.Xml-Frameworkkomponente
Im Code wird ein Import des System.Xml-Namensraums vorausgesetzt.
VB.NET-Quellcode
- Dim ifFile As New IniFile()
- Dim xmlWriter As New XmlTextWriter("settings.xml", Encoding.Default) 'Ausgabe in der aktuellen Zeichencodierung
- xmlWriter.WriteStartElement("settings") 'Stammelement oeffnen
- For Each section As IniFileSection In ifFile.Sections
- If section.IsCommentVisible Then
- xmlWriter.WriteComment(section.Comment) 'Kommentar schreiben, falls verfuegbar
- End If
- If section.IsSectionNameVisible Then
- xmlWriter.WriteStartElement(section.SectionName) 'Sektionselement oeffnen, falls verfuegbar
- End If
- For Each kvp As IniFileKeyValuePair In section.KeyValues
- If Not kvp.IsEmpty Then
- If kvp.IsCommentVisible Then
- xmlWriter.WriteComment(kvp.Comment) 'Kommentar schreiben, falls verfuegbar
- End If
- If Not kvp.IsComment Then 'Kommentar-Schluessel-Wert-Paare beruecksichtigen
- xmlWriter.WriteStartElement("setting") 'Eintrag oeffnen
- xmlWriter.WriteAttributeString("key", kvp.Key)
- xmlWriter.WriteAttributeString("value", kvp.Value)
- xmlWriter.WriteEndElement() 'Eintrag schliessen
- End If
- End If
- Next
- If section.IsSectionNameVisible Then
- xmlWriter.WriteFullEndElement() 'Sektionselement schliessen
- End If
- Next
- xmlWriter.WriteFullEndElement() 'Stammelement schliessen
- xmlWriter.Close()
Log
Version 2.3:
- Werte unterstützen nun auch den '='-Buchstaben (Bug im IniFileSerializer wurde damit behoben, da System.Type.AssemblyQualifiedName ein '=' enthalten kann)
- Fehlverhalten beim Auslesen von Streams auf Systemen mit CrLf- bzw. LfCr-Zeilenumsprüngen behoben, das zu leeren Schlüssel-Wert-Paaren führte
Version 2.2:
- Überarbeitung der IniFileSerializer-Klasse, die nun bereits bestehende Sektionen und Schlüssel-Wert-Paare überschreibt, statt neue anzulegen
Version 2.1:
- IniFileSerializer hinzugefügt (Anwendung siehe Anleitung)
Version 2.0:
- Die IniLib wurde komplett neu erstellt
Ich würde mich über Verbesserungsvorschläge, Anregungen und konstruktive Kritik freuen und werde Fragen gerne beantworten. Vielen Dank für den Download und viel Spaß mit der Entwicklung.
Mit freundlichen Grüßen
~blaze~
Edit by ~blaze~:
Sourcecode wurde verfügbar gemacht
--> *Thema aus dem Showroom verschoben*
Dieser Beitrag wurde bereits 19 mal editiert, zuletzt von „~blaze~“ ()