![]() |
FormatINI
Kleine procedure um INI Dateien zu formatieren.
Delphi-Quellcode:
function LeftStr(const Str: string; Size: Word): string;
begin Result := Copy(Str, 1, Size) end;
Delphi-Quellcode:
type
PParseFile = ^TParseFile; TParseFile = record Nr: Integer; Str: string; Ptr: PParseFile; Max: Integer; end;
Delphi-Quellcode:
var
LineStart: PParseFile; FPBuffer: PParseFile; FToPBuffer: PParseFile; nReading: Integer;
Delphi-Quellcode:
Mich ärgert immer wenn die Dateien zu unaufgeräumt sind.
procedure FormatINI(Filename: string);
var sBuffer: string; ParseFile: TextFile; StringList: TStringList; StringParse: string; procedure AppendToLinkedList(nReading: Integer; sBuffer: string); begin New(FPBuffer); if nReading = 0 then Begin New(FToPBuffer); LineStart := FToPBuffer; LineStart^.Nr := 0; end; FPBuffer^.Nr := nReading; FPBuffer^.Str := sBuffer; LineStart^.Max := FPBuffer^.Nr; FToPBuffer^.Ptr := FPBuffer; FToPBuffer := FPBuffer; end; begin StringList := TStringList.Create; Assignfile(ParseFile, Filename); reset(ParseFile); try try while not eof(ParseFile) do begin ReadLN(ParseFile, sBuffer); AppendToLinkedList(nReading, sBuffer); inc(nReading); end; except raise Exception.Create(SysErrorMessage(GetLastError)); end; finally nReading := 0; CloseFile(ParseFile); end; FPBuffer := LineStart; while (FPBuffer.Nr <= LineStart.Max - 1) do begin FPBuffer := FPBuffer.Ptr; StringParse := LeftTrim(FPBuffer.Str); if Length(StringParse) <> 0 then StringList.Add(FPBuffer^.Str); if FPBuffer.Nr > 0 then if LeftStr(FPBuffer^.Str, 1) = '[' then StringList.Insert(StringList.IndexOf(StringParse), ''); end; StringList.SaveToFile(Filename); StringList.Free; Dispose(FPBuffer); FPBuffer := nil; LineStart := nil; end; Die Ini wird so formatiert das vor jedem neuen Eintrag "[..]" eine Leerzeile eingefügt wird. Wer's braucht.. bitte schön. gruss |
AW: FormatINI
Gibt es einen Unterschied im Ergebnis zu diesem etwas knapperen hier?
Delphi-Quellcode:
procedure FormatINI(aFilename: String);
var f: TStringlist; i: Integer; begin f := TStringlist.Create; f.LoadFromFile(aFilename); // Remove blank lines i := 0; while i < f.Count do begin if Length(Trim(f[i]))=0 then f.Delete(i) else inc(i); end; // Add blank lines before section headers i := f.Count-1; while i>0 do begin if (Length(Trim(f[i]))>0) and (Trim(f[i])[0]='[') then f.Insert(i, ''); dec(i); end; f.SaveToFile(aFilename); f.Free; end; |
AW: FormatINI
Warum eigentlich umständlich AssignFile+ReadLn und nicht LoadFromFile?
Delphi-Quellcode:
StringList.LoadFromFile(Filename);
StringList.Text := ReplaceStr(StringList.Text, sLineBreak + '[', sLineBreak + sLineBreak + '['); StringList.SaveToFile(Filename);
Delphi-Quellcode:
// vielleicht auch sicherheitshalber so?
StringList.LoadFromFile(Filename); StringList.Text := ReplaceStr(ReplaceStr(StringList.Text, sLineBreak + sLineBreak, sLineBreak), sLineBreak + '[', sLineBreak + sLineBreak + '['); StringList.SaveToFile(Filename); |
AW: FormatINI
Zitat:
Zumal sie in dem Fall auch kürzer sind. Auf der anderen Seite warum erst speichern .. dann laden und anschließend wieder speichern. Macht irgendwie keinen Sinn den die Daten sind ja vorhanden. Ich wollte halt meine Ini Formatieren damit sie besser zum lesen ist. Und das Schnipsel wollte ich veröffentlichen falls es jemand braucht. Letztendlich führen viele Wege zum ziel. ;) Zitat:
Delphi-Quellcode:
JO warum soll ich erst leere Zeilen löschen ist unnötig.
procedure FormatINI(aFilename: String);
var f: TStringlist; i: Integer; begin f := TStringlist.Create; f.LoadFromFile(aFilename); // Remove blank lines i := 0; while i < f.Count do begin if Length(Trim(f[i]))=0 then f.Delete(i) else inc(i); end; // Add blank lines before section headers i := f.Count-1; while i>0 do begin if (Length(Trim(f[i]))>0) and (Trim(f[i])[0]='[') then f.Insert(i, ''); dec(i); end; f.SaveToFile(aFilename); f.Free; end; Wird bei mir in einem rutsch erledigt. bzw.. werden ignoriert wenn es leere Zeilen gibt. Und auch hier unnötige zugriffe auf die Datei warum nochmalig öffnen wenn sie schon geöffnet ist? gruss |
AW: FormatINI
Zitat:
Delphi-Quellcode:
StringList.LoadFromFile(Filename);
for i := StringList.Count - 1 downto 1 do if StartsStr('[', StringList[i]) and (StringList[i - 1] <> '') then // ich hoffe die Parameter bei StartsStr sind richtigrum StringList.Insert(i, ''); StringList.SaveToFile(Filename); |
AW: FormatINI
Zitat:
Nenne mir einen plausiblen Grund warum ich sie dann schließen, erneut laden und anschließend wieder speichern soll. Ich soll also zweimal eine Datei öffnen und zweimal schließen nur um ein paar Zeilen Code zu sparen? Welche Logik steckt dahinter? gruss |
AW: FormatINI
Neeeeeee, FormatINI öffnet die ja erst, also warum soll man sich selber die Mühe machen das zeilenweise manuell auszulesen? :wink:
|
AW: FormatINI
Zitat:
Dann werden die Daten geschrieben und anschließend direkt aufgeräumt. Ohne nach dem Schreiben die INI zu schließen anschließend wieder mit LoadFromFile zu öffnen und wieder zu schreiben und sie anschließend abermals zu schließen. Das war eigentlich der Hintergrund des ganzen. Natürlich geht es auch auf deinem weg aber mit unnötig vielen zugriffen auf die Datei selbst. :) Ich habe mir also schon etwas dabei gedacht warum ich es so mache. ;) gruss |
AW: FormatINI
In deiner geposteten Version öffnest du die Datei anhand ihres UNC-Pfads allerdings neu, dort sehe ich keinen direkten Griff auf ein TIniFile. Das Löschen bereits vorhandener Leerzeilen machst du implizit auch, allerdings relativ aufwendig, da du erst alles (exklusive der Leerzeilen) in eine weitere Liste schaufelst, um es dann mit neu eingefügten Leerzeilen wieder woanders hinzuschaufeln. Am Ende hast du genau so im Prinzip zwei Schleifen über alle Zeilen, wie ich auch. Allerdings eine Liste mehr: Deine als Puffer, und die Stringlist als Ziel und zum Speichern. Den Puffer halte ich für vermeidbar.
Du machst am Ende sogar mehr Dateizugriffe:
Delphi-Quellcode:
Während meine Variante lediglich:
// Datei zum Lesen öffnen
Assignfile(ParseFile, Filename); reset(ParseFile); // Datei schließen CloseFile(ParseFile); // Datei überschreiben StringList.SaveToFile(Filename);
Delphi-Quellcode:
Mir kam bei deiner Variante insbesondere das Gewerkel mit der selbst implementierten Liste unnötig aufgebläht und schwer lesbar daher, deswegen die Frage ob ich da weitere "Magie" übersehen habe. Die StringList ist ja schon eine hübsche fertige Liste mit der man hier gut arbeiten kann, und die jeder kennt. Das war eigentlich alles.
// Datei öffnen
f.LoadFromFile(aFilename); // Datei speichern und schließen f.SaveToFile(aFilename); Edit: Ich habe hier kein Delphi zur Hand, aber ich kann mir vorstellen, dass man den Text eines TIniFile relativ direkt in eine TStringList bekommt, ohne den Umweg über das vorherige Speichern zu gehen - welches deine Variante ja auch tut, so wie sie hier steht. Das wäre dann wirklich elegant. Edit2: Meine Version läst sich noch optimieren: Der Vergleich auf Länge 0 in der 2. Schleife ist doppelt gemoppelt. Es wurden ja gerade zuvor alle Zeilen gelöscht auf die das zutraf :stupid: |
AW: FormatINI
Zitat:
Siehe INI := TIniFile.Create(UserAppDataDir + bla..bla..); Zitat:
Zitat:
Oder täusche ich mich da? Kommt drauf an was du darunter verstehst. Ich öffne sie einmal und bearbeite die List dann anhand der geöffneten Datei. Anschließend wird sie auch nur einmal abgespeichert. Es geht um das doppelte und dreifache öffnen und schließen der gleichen Datei vom Datenträger. Warum das wenn sie schon offen ist? Einmal öffnen einmal schreiben und einmal schließen. Zitat:
gruss |
Alle Zeitangaben in WEZ +1. Es ist jetzt 11:09 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 by Thomas Breitkreuz