Hallo!
Ich habe in der Vergangenheit schon einige Male darüber geflucht, dass das TIniFile bzw. TMemIniFile doch relativ begrenzt ist in seinen Möglichkeiten. Am meisten fehlte mir die Möglichkeit, mehrzeilige Werte für die einzelnen Schlüssel verwenden zu können. Die Frage kam auch einige Male hier im Forum auf. Letztlich blieb es aber meist dabei, Zeilenumbrüche in irgendeiner Form mit StringReplace zu maskieren und den Wert dann einzeilig in der INI zu speichern.
Darüber hinaus gibt es noch die ein oder andere Möglichkeit, Sections oder Schlüssel umzubenennen ohne sie zu löschen und komplett neu zu schreiben. Dies hat ja immer den Nachteil, dass sich die Struktur/Reihenfolge in der INI-Datei verändert. Apropos Reihenfolge: Es gibt nun auch einige Procedures, mit denen man einzelne Schlüssel innerhalb der Section verschieben kann.
Die Fähigkeit, Schlüsselwerte mehrzeilig zu speichern, habe ich Heredoc-kompatibel (PHP-Style) implementiert:
Code:
[Section]
Key1=<<<HEREDOC_0
Line1
Line2
HEREDOC_0;
Key2=SingleLine
Um die Heredoc-Verwaltung muss man sich eigentlich nicht kümmern, die wird intern verwaltet. Bedingung ist, dass man die Konstruktoren entsprechend mit
SupportsHereDoc=TRUE
aufruft:
Delphi-Quellcode:
constructor Create(const FileName: string; const SupportsHereDoc: Boolean = FALSE); overload;
constructor Create(const FileName: string; const Encoding: TEncoding; const SupportsHereDoc: Boolean = FALSE); overload;
constructor Create(const Stream: TStream; const SupportsHereDoc: Boolean = FALSE); overload;
Es wird automatisch sichergestellt, dass es keine Überschneidungen mit dem Schlüsselwert-Inhalt gibt.
Folgende Funktionen habe ich zusätzlich noch ergänzt:
Delphi-Quellcode:
function KeyIndex(const Section, Ident: string): Integer; virtual;
function MoveKey(const Section, Ident: string; const NewPosition: Integer): Integer; virtual;
function MoveKeyUp(const Section, Ident: string): Integer; virtual;
function MoveKeyDown(const Section, Ident: string): Integer; virtual;
function MoveSection(const Section: string; const NewPosition: Integer): Integer; virtual;
function MoveSectionUp(const Section: string): Integer; virtual;
function MoveSectionDown(const Section: string): Integer; virtual;
function RenameKey(const Section, OldKeyName, NewKeyName: string): Boolean; virtual;
function RenameSection(const OldName, NewName: string): Boolean; virtual;
function SectionIndex(const Section: string): Integer; virtual;
procedure SaveToFile(const FileName: string); virtual;
Das ganze ist eine Reimplementation der System.IniFiles und basiert zu einem Teil auch darauf. Leider konnte ich die Klassen nicht einfach davon ableiten, weil die Standard-Klassen "bescheiden" implementiert sind und indirekte Sichtbarkeiten verwenden, die außerhalb der
Unit System.IniFiles nicht verfügbar sind. Zum Beispiel: Ein Zugriff auf die private Variable FFileName der Elternklasse aus der abgeleiteten Kindklasse heraus - wohl weil
property FileName
nur Readonly implementiert ist. Einfach schlechtes Code-Design seitens *IhrWisstSchonWer*
Wichtiger Hinweis zum Schluss: Bei der Verwendung mehrzeiliger Heredoc-INIs möge man bedenken, dass sie auch nur von dieser Implementierung gelesen werden können. Andere Programme, insbesondere diejenigen, die GetPrivateProfileString verwenden, können solche INIs
nicht lesen! Solange man sich aber in seinem eigenen Ökosystem bewegt, ist das kein Problem. Und vielleicht greift ja Microsoft die Idee auf und implementiert für GetPrivateProfileString/WritePrivateProfileString auch noch eine Heredoc-Kompatibilität
Siehe auch
Wikipedia: Heredoc
Viel Spaß damit und Feedback ist willkommen!
Grüße
Cody