![]() |
UniversalDataUnit
Hallo DP'ler,
ich habe immer wieder mit den verschiedensten Konfigurationsdaten zu tun und habe mich entschieden eine Universelle Unit dafür zu schreiben und sie zu erweitern wann immer es nötig ist. Da ich bei meinem neusten Projekt mit INI-Dateien zu tun habe, habe ich nun angefangen die Unit zu programmieren. Der Code darf für alles verwendet werden, da er eigentlich keinen grossen Wert hat - könnte höchstens ne halbe bis ganze Stunde Programmierarbeit ersparen :)
Delphi-Quellcode:
Ich habe versucht den Code so kurz wie möglich zu halten. Es gibt auch viel Optimierungspotenzial aber da ich nun Feierabend(mittag :D) habe, werde ich erst morgen weiter machen können.
// --------------------------------------------------------------------------
// UniversalConfigUnit // Version 0.1DPP (DelphiPraxis Preview) // -------------------------------------------------------------------------- // There is no limitation with this code. // If you want to use, change and/or upload the code, just do it =) // -------------------------------------------------------------------------- // Features: // - INI Files // - Create INI Object // - Load File to Object // - Parse String/TStringList to Object // - Save Object to File // -------------------------------------------------------------------------- // Authors: // Stanojevic Milos // Email: contact@svr2k.de // // (add yourself here) // -------------------------------------------------------------------------- unit UniversalConfigUnit; interface uses Generics.Collections, Classes, SysUtils, System.RegularExpressions; type { INI CLASSES START } TIniSection = class private FValues : TDictionary<string, string>; function FGetValue(AKey: string) : string; procedure FSetValue(AKey : string; AProperty : string); public Title : string; constructor Create(ATitle : string); function ContainsKey(AKey : string): Boolean; property Value[AKey : string] : string read FGetValue write FSetValue; default; end; TIniObject = class private FSections : TList<TIniSection>; function FGetSection(AIndex : string) : TIniSection; function FGetValue(ASection, AKey : string) : string; function FGetTitle(AIndex : integer) : string; public constructor Create(); procedure Parse(AStringList : TStringList); procedure LoadFromFile(AFileName : string); procedure SaveToFile(AFileName : string); function ContainsSection(ASection : string) : Boolean; procedure AddSection(AIniSection : TIniSection); procedure AddValue(ASection, AKey, AProperty : string); overload; procedure AddValue(ASection, AKey, AProperty : string; AAutoCreate : boolean); overload; property Section[Index : string] : TIniSection read FGetSection; default; property Value[index, Index2: string] : string read FGetValue; property Title[index : integer] : string read FGetTitle; end; { INI CLASSES END } implementation { TIniConfig } procedure TIniObject.AddSection(AIniSection: TIniSection); var LIndex : integer; begin LIndex := FSections.Add(AIniSection); end; procedure TIniObject.AddValue(ASection, AKey, AProperty: string); begin Section[ASection].FValues.Add(AKey, AProperty); end; procedure TIniObject.AddValue(ASection, AKey, AProperty: string; AAutoCreate : boolean); begin if AAutoCreate then begin if ContainsSection(ASection) then AddValue(ASection, AKey, AProperty); end else begin AddSection(TIniSection.Create(ASection)); AddValue(ASection, AKey, AProperty); end; end; function TIniObject.ContainsSection(ASection: string): Boolean; var c: Integer; begin for c := 0 to FSections.Count-1 do if FSections[c].Title = ASection then Result := true; end; constructor TIniObject.Create; begin FSections := TList<TIniSection>.Create(); end; function TIniObject.FGetSection(AIndex : string): TIniSection; var c: Integer; begin for c := 0 to FSections.Count-1 do if FSections[c].Title = AIndex then Result := FSections[c]; if Result = nil then raise Exception.Create(AIndex + ' konnte nicht gefunden werden'); end; function TIniObject.FGetTitle(AIndex: integer): string; begin Result := FSections[AIndex].Title; end; function TIniObject.FGetValue(ASection, AKey: string): string; begin Result := Section[ASection][AKey]; end; procedure TIniObject.LoadFromFile(AFileName: string); var LStringList : TStringList; begin if FileExists(AFileName) then begin LStringList := TStringList.Create; LStringList.LoadFromFile(AFileName); Parse(LStringList); end else raise Exception.Create(AFileName + ' wurde nicht gefunden'); LStringList.Free; end; procedure TIniObject.Parse(AStringList: TStringList); var LLine : string; LParts : TStringList; c: Integer; begin LParts := TStringList.Create; for c := 0 to AStringList.Count - 1 do begin LLine := AStringList[c]; if Length(LLine) < 1 then Continue; if LLine[1] = ';' then Continue else if (LLine[1] = '[') and (LLine[Length(LLine)] = ']') then begin AddSection(TIniSection.Create(Copy(LLine,2,Length(LLine)-2))); Continue; end else if (TRegEx.IsMatch(LLine, '^[a-zA-Z0-9]*=[a-zA-Z0-9(./)]*$')) then begin LParts.Clear; LParts.StrictDelimiter := true; LParts.Delimiter := '='; LParts.DelimitedText := LLine; FSections[FSections.Count-1].FValues.Add(LParts[0],LParts[1]); end else raise Exception.Create('Fehler beim laden der INI-Datei.' + #10 + 'Zeile: ' + IntToStr(c + 1) + #10 + '"' + LLine + '" ist keine gültige INI Anweisung.'); end; LParts.Free; end; procedure TIniObject.SaveToFile(AFileName: string); var LStringList : TStringList; LPair : TPair<string, string>; c: Integer; begin LStringList := TStringList.Create; for c := 0 to FSections.Count-1 do begin LStringList.Add('[' + FSections[c].Title + ']'); for LPair in FSections[c].FValues do LStringList.Add(LPair.Key + '=' + LPair.Value); LStringList.Add(''); end; LStringList.SaveToFile(AFileName); LStringList.Free; end; { TIniSection } function TIniSection.ContainsKey(AKey : string): Boolean; var c: Integer; begin Result := FValues.ContainsKey(AKey); end; constructor TIniSection.Create(ATitle : string); begin Title := ATitle; FValues := TDictionary<string, string>.Create; end; function TIniSection.FGetValue(AKey: string): string; begin Result := FValues[AKey]; end; procedure TIniSection.FSetValue(AKey, AProperty: string); begin if ContainsKey(AKey) then FValues[AKey] := AProperty; end; end. Ich freue mich über jede Verbesserungsvorschläge oder sonstigen Anmerkungen. Freundliche Grüsse |
AW: UniversalConfigUnit
Willst du die ganzen MemLeaks noch beseitigen? :stupid:
|
AW: UniversalConfigUnit
Hi :)
Ja die paar MemoryLeaks werden noch gefixt ;) Habe mir auch noch ein paa Sachen überlegt die man besser machen könnte. Hat sonst noch jemand Vorschläge oder Kritikpunkte? Bin für alles offen :thumb: |
AW: UniversalConfigUnit
Ich habe die Implementation jetzt noch nicht gelesen, aber ich verstehe nicht, was denn nun eine
Delphi-Quellcode:
und was ein
TIniSection
Delphi-Quellcode:
ist. Eine Sektion scheint einen änderbaren Titel und String-String-Paare zu besitzen. Ein
TIniObject
Delphi-Quellcode:
scheint nun beliebig viele dieser Sektionen sowie beliebig viele Titel (?) zu beinhalten. Wenn ich es richtig verstehe wäre doch "TIniFile" ein passenderer Name, oder?
TIniObject
Vorausgesetzt ich liege nicht meilenweit daneben, verstehe ich eins noch nicht: Wo ist nun der Unterschied von TIniObject zum in Delphi bereits vorhandenen TIniFile? :| |
AW: UniversalConfigUnit
Kannst du mal den Vorteil gegenüber einer TMemIniFile erörtern? Denn für mich sieht das nach einem flüchtigen Blick genau danach aus.
|
AW: UniversalConfigUnit
Füg' doch noch die Methode
Delphi-Quellcode:
und
LoadFromStream()
Delphi-Quellcode:
hinzu.
SaveToStream()
Denn ein File ist ja nur die Spezialisierung eines Streams; und wer weiß vielleicht willst du die Konfiguration ja mal von einem Webserver auslesen. Natürlich rufen die Methoden LoadFromFile() und SaveToFile() ihre allgemeineren Streamvarianten auf und übergeben ein FileStream-Objekt.
Delphi-Quellcode:
procedure TIniObject.Parse(AStringList: TStringList); // falsch: TStringList ist zu spezifisch
procedure TIniObject.Parse(AStringList: TStrings); // richtig: TStrings bietet dem Aufrufer alle Möglichkeiten |
AW: UniversalConfigUnit
Zitat:
Zitat:
Zitat:
Zufälligerweise hatte ich schon ein Problem mit der StringList :oops: Habe auch noch etwas kleines aber doofes bemerkt: Erstmal ein schneller Crashkurs: TIniObject beinhaltet die ganze IniDatei mit allen Sektionen. TIniSection ist eine Sektion bei der, der Titel immer mit eckigen Klammern umgeben sind und dessen Eigenschaften unten aufgeführt sind. Es gibt folgende Wege eine Eigenschaft auszulesen:
Delphi-Quellcode:
Ich denke mal die Value variante wird raus genommen, da sie eigentlich unnötig ist. ^^
IniObject[Sektion][Eigenschaftsvariable] : Eigenschaftswert als String
IniObject.Value[Sektion, Eigenschaftsvariable] : Eigenschaftswert als String Freundliche Grüsse |
Alle Zeitangaben in WEZ +1. Es ist jetzt 22:12 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz