Autor Beitrag
jasocul
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 6386
Erhaltene Danke: 146

Windows 7 + Windows 10
Sydney Prof + CE
BeitragVerfasst: Mi 26.10.05 09:15 
Soweit ich feststellen konnte, gibt es unter .NET leider nicht etwas so schönes, wie die Unit TINIFiles. Daher habe ich mich daran gemacht, etwas Eigenes zu machen. Basis dafür sind XML-Dateien. Angeregt wurde ich von einer ähnlichen Lösung aus diesem Buch:

Zitat:
Delphi 2005
(Delphi programmieren mit dem .NET Framework)
von Elmar Warken
Verlag: Addison-Wesley
ISBN: 3-8273-2193-X

und der Notwendigkeit, dass ich etwas in der Art brauchte. Im Prinzip ist das also nur ein Abfallprodukt.
Die Lösung aus dem Buch gefiel mir persönlich aber noch nicht ganz. Daher habe ich da mal etwas rumgebastelt. Verzeiht mir, dass es noch nicht in C# geschrieben ist. Wer Lust hat kann das ja entsprechend umschreiben und hier zur Ergänzung reinschreiben.

Zur Unit:
Es gibt 3 Klassen. Die Basisklasse TXmlIniFileBase würde theoretisch genügen, alles abzuarbeiten. Da ich aber nicht immer ein "ToString" verwenden möchte, habe ich eine weitere Klasse abgeleitet: TXmlIniFile. Dort sind die Write- und Read-Methoden überladen. Dadurch können unter gleichem Methodennamen verschiedene Typen übergeben werden. Diese Klasse ist für weitere Typen problemlos zu erweitern. Die letzte Klasse TXmlIniFileOldStyle, Habe ich nur gemacht, damit die "alten" Methoden-Aufrufe aus TINIFile benutzen kann. Ich selbst verwende diese Klasse nicht.

Was diese Klassen nicht machen:
Vorhandene INI-Dateien (und die Registry) können damit nicht gelesen und bearbeitet werden. Es ist also etwas völlig anderes.

Erläuterungen:
Eigentlich wird alles wichtige in der Basis-Klasse gemacht. Die vererbten Klassen greifen eigentlich nur darauf zu.
Mit der Eigenschaft AutoSave kann eingestellt werden, ob nach jedem WriteData die Daten auch physisch geschreiben werden sollen. Aus Performance-Gründen ist False voreingestellt. Sollen die Daten gespeichert werden, ist die Methode SaveData manuell aufzurufen.
Kommentar im Source gibt es nicht, da ich denke, dass der Source relativ einfach ist. Sollte etwas unverständlich sein, schreibt hier rein, was nocht klar ist. Ich werde dass im Source dann entsprechend deutlich machen.

ausblenden volle Höhe Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67:
68:
69:
70:
71:
72:
73:
74:
75:
76:
77:
78:
79:
80:
81:
82:
83:
84:
85:
86:
87:
88:
89:
90:
91:
92:
93:
94:
95:
96:
97:
98:
99:
100:
101:
102:
103:
104:
105:
106:
107:
108:
109:
110:
111:
112:
113:
114:
115:
116:
117:
118:
119:
120:
121:
122:
123:
124:
125:
126:
127:
128:
129:
130:
131:
132:
133:
134:
135:
136:
137:
138:
139:
140:
141:
142:
143:
144:
145:
146:
147:
148:
149:
150:
151:
152:
153:
154:
155:
156:
157:
158:
159:
160:
161:
162:
163:
164:
165:
166:
167:
168:
169:
170:
171:
172:
173:
174:
175:
176:
177:
178:
179:
180:
181:
182:
183:
184:
185:
186:
187:
188:
189:
190:
191:
192:
193:
194:
195:
196:
197:
198:
199:
200:
201:
202:
203:
204:
205:
206:
207:
208:
209:
210:
211:
212:
213:
214:
215:
216:
217:
218:
219:
220:
221:
222:
223:
224:
225:
226:
227:
228:
229:
230:
231:
232:
233:
234:
235:
236:
237:
238:
239:
240:
241:
242:
243:
244:
245:
246:
247:
248:
249:
250:
251:
252:
253:
254:
255:
256:
257:
258:
unit JSCTools.XMLINIFiles;
{Source von: Peter Schrade
Homepage: www.jasocul.de}


interface

uses
  System.Xml, System.IO;

type
  TXmlIniFileBase = class
  private
    FDocument : XmlDocument;
    FFileName : &string;
    FAutoSave : &Boolean;
  published
    property FileName : String read FFileName;
    property AutoSave : Boolean read FAutoSave write FAutoSave Default False;
    procedure WriteData(Section, Ident : String; Value : String); overloadvirtual;
    function ReadData(Section, Ident, Default : String) : stringoverloadvirtual;
  public
    constructor Create(FileName : string; ElementName : String);
    procedure SaveData; virtual;
  end;

  TXmlIniFile = class(TXmlIniFileBase)
    constructor Create(FileName : string; ElementName : String);
    procedure WriteData(Section, Ident : String; Value : Longint); overloadvirtual;
    procedure WriteData(Section, Ident : String; Value : Boolean); overloadvirtual;
    procedure WriteData(Section, Ident : String; Value : Double); overloadvirtual;
    function ReadData(Section, Ident : StringDefault : Longint) : Longint; overloadvirtual;
    function ReadData(Section, Ident : StringDefault : Boolean) : Boolean; overloadvirtual;
    function ReadData(Section, Ident : StringDefault : Double) : Double; overloadvirtual;
  end;

  TXmlIniFileOldStyle = class(TXmlIniFileBase)
    constructor Create(FileName : string; ElementName : String);
    procedure WriteString(Section, Ident : String; Value : String); virtual;
    procedure WriteInteger(Section, Ident : String; Value : Longint); virtual;
    procedure WriteBool(Section, Ident : String; Value : Boolean); virtual;
    procedure WriteFloat(Section, Ident : String; Value : Double); virtual;
    function ReadString(Section, Ident : StringDefault : String) : Stringvirtual;
    function ReadInteger(Section, Ident : StringDefault : Longint) : Longint; virtual;
    function ReadBool(Section, Ident : StringDefault : Boolean) : Boolean; virtual;
    function ReadFloat(Section, Ident : StringDefault : Double) : Double; virtual;
  end;

implementation

// ************* Base ****************************

constructor TXmlIniFileBase.Create(FileName : string; ElementName : String);
begin
  inherited Create;

  FDocument := XmlDocument.Create;
  if System.Io.File.Exists(FileName) then
  begin
    FDocument.Load(FileName);
  end
  else
  begin
    FDocument.AppendChild(FDocument.CreateElement(ElementName));
  end;
  FAutoSave := False;
  FFileName := FileName;
end;

procedure TXmlIniFileBase.WriteData(Section, Ident : String; Value : String);
var
  Nodes : XmlNodeList;
  XMLSection, XMLElem : XmlNode;
begin
  if Value <> '' then
  begin
  // value ist zwar vom Typ String, aber wenn man Leer-Strings übergibt, werden die u.U. 
  // als Nil interpretiert. Die Folge ist, dass die Zuweisung an InnerText extrem langsam wird.
  // Daher ist eine Speicherung von Leer-Strings erstmal rausgenommen.
  // Für Anregungen wäre ich dankbar.

    Nodes := FDocument.DocumentElement.GetElementsByTagName(Section);
    if Nodes.Count > 0 then
    begin
      XMLSection := Nodes[0];
    end
    else
    begin
      XMLSection := FDocument.CreateElement(Section);
      FDocument.DocumentElement.AppendChild(XMLSection);
    end;
    Nodes := (XMLSection as XmlElement).GetElementsByTagName(Ident);
    if Nodes.Count > 0 then
    begin
      XMLElem := Nodes[0];
    end
    else
    begin
      XMLElem := FDocument.CreateElement(Ident);
      XMLSection.AppendChild(XMLElem);
    end;
    XMLElem.InnerText := value;

    if FAutoSave then
      SaveData;
  end;
end;

function TXmlIniFileBase.ReadData(Section, Ident, Default : string) : string;
var
  Nodes : XmlNodeList;
  XMLSection, XMLElem : XmlNode;
begin
  Result := Default;
  Nodes := FDocument.DocumentElement.GetElementsByTagName(Section);
  if Nodes.Count > 0 then
  begin
    XMLSection := Nodes[0];
    Nodes := (XMLSection as XmlElement).GetElementsByTagName(Ident);
    if Nodes.Count > 0 then
    begin
      XMLElem := Nodes[0];
      Result := XMLElem.InnerText;
     end;
  end;
end;

procedure TXmlIniFileBase.SaveData;
begin
  FDocument.Save(FileName);
end;

// *************** INI-File ****************************************

constructor TXmlIniFile.Create(FileName : string; ElementName : String);
begin
  inherited Create(FileName, ElementName);
end;

procedure TXmlIniFile.WriteData(Section, Ident : string; Value : Boolean);
begin
  WriteData(Section, Ident, Value.ToString);
end;

procedure TXmlIniFile.WriteData(Section, Ident : string; Value : Double);
begin
  WriteData(Section, Ident, Value.ToString);
end;

procedure TXmlIniFile.WriteData(Section, Ident : string; Value : Integer);
begin
  WriteData(Section, Ident, Value.ToString);
end;

function TXmlIniFile.ReadData(Section, Ident : string; Default : Boolean) : Boolean;
var
  vStr : string;
begin
  vStr := ReadData(Section, Ident, '');
  if vStr = '' then
    Result := Default
  else
    Result := System.Boolean.Parse(vStr);
end;

function TXmlIniFile.ReadData(Section, Ident : string; Default : Double) : Double;
var
  vStr : string;
begin
  vStr := ReadData(Section, Ident, '');
  if vStr = '' then
    Result := Default
  else
    Result := System.Double.Parse(vStr);
end;

function TXmlIniFile.ReadData(Section, Ident : string; Default : Integer) : Longint;
var
  vStr : string;
begin
  vStr := ReadData(Section, Ident, '');
  if vStr = '' then
    Result := Default
  else
    Result := Int16.Parse(vStr);
end;

//**************** OldStyle *****************************

constructor TXmlIniFileOldStyle.Create(FileName : string; ElementName : String);
begin
  inherited Create(FileName, ElementName);
end;

procedure TXmlIniFileOldStyle.WriteBool(Section, Ident : string; Value : Boolean);
begin
  WriteData(Section, Ident, Value.ToString);
end;

procedure TXmlIniFileOldStyle.WriteFloat(Section, Ident : string; Value : Double);
begin
  WriteData(Section, Ident, Value.ToString);
end;

procedure TXmlIniFileOldStyle.WriteInteger(Section, Ident : string; Value : Integer);
begin
  WriteData(Section, Ident, Value.ToString);
end;

procedure TXmlIniFileOldStyle.WriteString(Section, Ident : string; Value : String);
begin
  WriteData(Section, Ident, Value.ToString);
end;

function TXmlIniFileOldStyle.ReadBool(Section, Ident : string; Default : Boolean) : Boolean;
var
  vStr : string;
begin
  vStr := ReadData(Section, Ident, '');
  if vStr = '' then
    Result := Default
  else
    Result := System.Boolean.Parse(vStr);
end;

function TXmlIniFileOldStyle.ReadFloat(Section, Ident : string; Default : Double) : Double;
var
  vStr : string;
begin
  vStr := ReadData(Section, Ident, '');
  if vStr = '' then
    Result := Default
  else
    Result := System.Double.Parse(vStr);
end;

function TXmlIniFileOldStyle.ReadInteger(Section, Ident : string; Default : Integer) : Longint;
var
  vStr : string;
begin
  vStr := ReadData(Section, Ident, '');
  if vStr = '' then
    Result := Default
  else
    Result := Int16.Parse(vStr);
end;

function TXmlIniFileOldStyle.ReadString(Section, Ident : string; Default : String) : String;
var
  vStr : string;
begin
  vStr := ReadData(Section, Ident, '');
  if vStr = '' then
    Result := Default
  else
    Result := vStr;
end;

end.

[meta]INI,INI-Dateien,Settings[/meta]