![]() |
INI-Datei sortieren
Hallo
Ich nutze eine INI-Datei als "Datenbank". Diese sieht in etwa so aus: [.] anzahl=2134 [1] date=08.12.1998 aus=3,2 ein=0 z=1 e=2 ... [2134] date=20.07.2005 aus=3,2 ein=0 ss=2 fz=1 ns=1 nz=1 Jeder dieser Einträge enthält ein Datum. Alle anderen Einträge können variieren. Das Datum kann aber "von Hand" gesetzt werden. So kommt es vor das die Einträge nicht in der richtigen Reihenfolge sind. Das ist jedoch für den Programmablauf sehr wichtig. Da sonst die Anzeigen falschsein können. Nun habe ich mir eine Sortierfunktion geschrieben die aber leider sehr Resourcenfressend ist. Und mich so etwas festgefahren. Vielleicht kann mir jemand helfen und mir ein paar Tipps geben wie man das möglichst Simple machen kann (so das es auch ein 286'er schafft). Vielleicht noch schnell hinten ran: Das Programm ist aus der Zeit in der ich mich noch nicht an Datenbanken traute. Und nun ist es auch nicht mehr möglich es zu ändern. Also es helfen mir keine "Datenbank-Tipps". Bitte nur Hinweise wie ich diese INI nach Datum sortieren kann. Vielen Dank im vorraus MfG |
Re: INI-Datei sortieren
Sorry, aber dazu will ich dir nicht wirklich einen Tipp geben. Die Lösung ist nun mal eine Datenbank. Ini Files sind dafür einfach nicht gedacht.
Aber das wolltest du ja gerade nicht hören. :roll: Aber dennoch wäre es vielleicht eine Ueberlegung wert, auf Datenbanken umzusteigen, alleine schon wegen der Performance. |
Re: INI-Datei sortieren
Wenn du schon eine Ini als Datenbank missbrauchst, dann bitte richtig :wink: . Bei einer Ini kann es nicht auf die Reihenfolge, sondern nur auf die Struktur der Werte ankommen. Deine Routine zum Einlesen muss also einen (Denk-)Fehler haben. Wenn du die Datei doch lieber sortieren willst: Zeig doch erstmal deinen bisherigen Code.
|
Re: INI-Datei sortieren
Das vertauschen der einzelnen Einträge sollte kein Problem sein. Die Frage, die sich mir dabei als erstes gestellt hat: Wie greift man effizient auf das Datum am Index X zu?
Effizient kann nun bedeuten schnell oder ressourcensparend. Eine schnelle Möglichkeit zum Sortieren könnte so aussehen: Eine Funktion berechnet die Zeilennummer des jeweiligen Datums und speichert diese in einem Array. Nun könnten mittels Heap-Sort (hier effizienter als Quicksort, da das Feld schon vorsortiert ist) schnell die einzelnen Einträge umsortiert werden. Dabei bleibt aber zu beachten, dass die im Array gespeicherten Zeilen auch nach Tauschvorgängen im Feld immer noch die korrekten Daten enthalten. Dafür müsste dann die Methode zum Vertauschen sorgen. Dieser Vorschlag hat den Nachteil, das ein großes Array erzeugt werden muss. Dafür sollte das Sortieren aber schnell funktionieren. Eine ressourcensparende Variante fällt mir spontan nicht ein... |
Re: INI-Datei sortieren
Den Code zum sortieren direkt habe ich noch nicht geschrieben. Aber ich habe in einem anderen Programm das auch schon so gemacht. Bei dem kam es auf das löschen eines Eintrages an. Dieser Code enthält für alle Einträge ein eigenes Array das in dem Fall "NUR" für 1000 Einträge arbeitet. Wenn in der INI-Datei nun ein Eintrag gelöscht werden soll rücken alle Einträge um einen nach vorn. Diese dauert auf einem P2 mit 500MHz ca. 2min.
Wenn ich auf dieselbe Weise diese INI-Datei sortiere habe ich nun zwei Probleme. Zum einen ist der Zeitfaktor bei ca. 2500 Einträgen enorm. Und zum anderen ist bei dieser INI nicht immer jeder Eintrag vorhanden (aus Dateigrößengründen). Nun hofft ich eigentlich das einer von Euch soetwas wie: -Das wurde schon gefragt ... Kuck mal da. Oder -Nutze doch einfach "SORTINI". Oder -So etwas in der Art Ich möchte die Funktion um das zu sortieren nicht Stundenlang tippen um dann zu sagen das es einfach viel zu lange dauert und das ganze dann wieder löschen. Mein Problem ist das man sich die letzten 10 bis 50 Einträge dieser "INI" anzeigen lassen kann. Und diese müssen eben die aktuellsten Daten sein. Vielleicht gibt es ja einen anderen Weg das zu machen. Aber mir raucht einfach nur der Schädel und ich krieg das nicht mehr hin. Immer wenn ich mich ran setze komm ich wieder in die selbe Richtung. Und das hat einfach keinen Sinn. |
Re: INI-Datei sortieren
Eventuell würde es auch schon Sinn machen, beim Einfügen eines neuen Records diese sofort an der richtigen Stelle einzufügen. Beim Aendern ebenfalls... Das macht natürlich nur Sinn, wenn du immer nur nach Datum sortieren willst, und nicht auch mal nach anderen Werten. Aber wie gesagt, setze um auf eine DB. So aufwendig ist das sicherlich nicht.
|
Re: INI-Datei sortieren
Mich würde mal der Grund interessieren warum eine DB nicht mehr möglich ist? Ich denke ein kleiens Tool zu schreiben das vorhandenen INI-Files in die DB schreibt ist einfacher als sich den Kopf über eine Sortierfunktion für eine INI zu zerbrechen. Oder gibt es einen anderen Grund?
|
Re: INI-Datei sortieren
Grundsätzlich ist die Erstellung einer Sortierfolge für die beschriebene Steuerdatei nicht schwierig. Mich irritieren nur Anforderungen, wie "muss sortiert gespeichert werden, sonst Anzeigeproblem" und "Lücken im Nummerkreis wegen Dateigrößenproblem". Wenn die Umstellung auf eine lokale Datenbank keine Option ist, dann kann man das Größenproblem durch eine BigIni-List aus der Welt schaffen. Die Sortierfolge lässt sich dann durch einen sortierfähigen Datum-String (DIN 2005-08-14 oder ANSI 20050814) in einer TStringList herstellen. Mit sl.AddObject(sDatum, Pointer(key)) kann dann durch die automatische Sortierung (sl.Sorted := true) ein Index erstellt werden, der mit Integer(sl.Objects[i]) die indexsequentielle Abschnittsnummer liefert.
Grüße vom marabu |
Re: INI-Datei sortieren
Also ...
Dieses Prog ist seit X Jahren im Einsatz. Wird auf X Rechnern verwendet. Selbst wenn ich die Source dazu finde habe ich, denke ich zumindest, nicht die Muse mich da nochmal reinzulesen und das ganze auf eine DB zu ändern. Nun hat mich einer dieser X User wegen dem Problem der Anzeige der Einträge kontaktiert. Und ich würde ihm einfach ein Tool bauen wollen das diese INI sortiert. Ohne das man noch irgend etwas machen muß. @marabu: Das klingt als ob es eine eifache Lösung gebe. Ich verstehe nur leider nur BAHNHOF. Könntest du das eventuell etwas einfacher und genauer beschreiben? MfG |
Re: INI-Datei sortieren
Zitat:
Ich hätt da noch so eine Idee, wie du dieses Tool aufbauen kannst, denn es spricht ja nun nichts dagegen, für dieses Tool eine Datenbank zu verwenden. Da fällt mir spontan die VirtualTable Komponente von crlab.com ein, die im Paket MyDAC drinn ist. Ist ne Art Datenbank im Speicher, aber mit allem was SQL zu bieten hat... Also hier meine Idee: 1. Exportiere die gesamte INI Datei in eine Datenbanktabelle. Die Spaltennamen kannst du ja nach den Values aus der INI basieren. Als Primary Key nimmst du die Section Ueberschrift. 2. Du baust die ein SQL Statement
SQL-Code:
3. Du durchläufst dein Resultset und erstellt die INI Datei komplett neu indem du einfach jeden einzelnen Record exportierst.
select * from Tabelle order by Datum
Ich könnt mir vorstellen, dass das bei 2000 Records noch ziemlich flott vonstatten geht. |
Re: INI-Datei sortieren
Zitat:
Delphi-Quellcode:
Grüße vom marabu
uses
Classes, IniFiles, SysUtils; const tmj = 'dd.mm.yyyy'; jmt = 'yyyy-mm-dd'; function ReformatStr(const s, sRule: string): string; var i: integer; begin Result := ''; for i := 1 to Length(sRule) do Result := Result + s[Ord(sRule[i])]; end; function ZeroPad(const i: cardinal; size: byte): string; begin Result := IntToStr(i); if Length(Result) < size then Result := StringOfChar('0', size - Length(Result)) + Result; end; procedure IniSort; var ini: TMemIniFile; s, sKey, sSection: string; slSort, slValues, slSection: TStringList; i, j, iAnzahl: integer; begin slSort := TStringList.Create; slSection := TStringList.Create; ini := TMemIniFile.Create(ParamStr(1)); iAnzahl := ini.ReadInteger('.', 'anzahl', 0); for i := 1 to iAnzahl do begin sSection := IntToStr(i); if ini.SectionExists(sSection) then begin s := ini.ReadString(sSection, 'Datum', ''); s := ReformatStr(s, #7#8#9#10#4#5#1#2); ini.ReadSectionValues(sSection, slSection); s := s + ZeroPad(i, 4); slValues := TStringList.Create; slValues.Assign(slSection); slSort.AddObject(s, slValues); end; end; slSort.Sort; ini.Clear; ini.WriteString('.', 'Anzahl', IntToStr(iAnzahl)); for i := 0 to slSort.Count - 1 do begin sSection := Copy(slSort[i], 9, 4); sSection := IntToStr(StrToInt(sSection)); slSection := TStringList(slSort.Objects[i]); for j := 0 to slSection.Count - 1 do begin sKey := slSection.Names[j]; ini.WriteString(sSection, sKey, slSection.Values[sKey]); end; slSection.Free; end; ini.UpdateFile; ini.Free; slSort.Free; end; |
Re: INI-Datei sortieren
@marabu:
Zunächst mal VIELEN, VIELEN, VIELEN Dank, das Du Dir die Mühe gemacht hast das zu Proggen. Es ist rasend schnell. Aber leider sortiert es nicht so wie ich es erhoffte. Nach was da genau sortiert wird kann ich nocht nicht mal sagen, es ist irgendwie umsortiert, aber ich finde kein Schema. Und leider bleiben ja auch die Nummerierungen gleich. Doch genau diese sollen ja nach Datum sortiert sein. @Jelly: Muß für die Komponete nicht auf dem anderen Rechener auch die BDE installiert sein? MfG |
Re: INI-Datei sortieren
Hi st18061974,
ich vermute mal, du musst noch das Literal 'Datum' in meinem Code nach 'date' abändern, damit deine Datei wirklich sortiert wird... Grüße vom marabu |
Re: INI-Datei sortieren
Hallo marabu
Nein, das habe ich natürlich gemacht. Und ich habe jetzt das "Sortiershema" erkannt. Die in der INI gespeicherten Einträge werden nach der ersten Zahl sortiert. Also 1,2, ... 10,11 u.s.w. und zwar im Bezug auf Monat und Jahr. Allerdings von 2000 nach 2005 und dann von 1998 und 1999. Noch dazu ist mittedrin irgendwie ein Sprung an dem sie wieder bei 2000 anfängt. Ich vermute mal, da ich den Script nur bedingt kappiere, das es daran liegt das hier Strings sortiert werden und keine Daten. Das ist aber auch alles nicht so Wild. Die INI wird nämlich nicht umsortiert sonder nur umstruckturiert. Tatsächlich bleiben alle Einträge bei Ihrem jeweiligen Zähler. Ich habe hier mal ein Vorher - Nachher - Bild. Bei diesem auslesen habe ich vor dem sortieren die letzte 100 ausgelesen und danach. Wie man sehen kann hat sich da nicht verändert. ![]() MfG |
Re: INI-Datei sortieren
Du Schlingel,
in deinem ersten Posting hast du das Datum mit führenden Nullen bei Tag und Monat angegeben und darauf ist mein Code ausgerichtet. Wenn du ohne führende Nullen arbeiten willst, dann musst du die Funktion ReformatStr() durch die Funktion ReformatDate() ersetzen:
Delphi-Quellcode:
Heitere Grüße vom marabu
function ReformatDate(s: string): string;
var i, d,m,y: integer; begin i := Pos('.', s); d := StrToInt(Copy(s, 1, Pred(i))); Delete(s, 1, i); i := Pos('.', s); m := StrToInt(Copy(s, 1, Pred(i))); Delete(s, 1, i); y := StrToInt(s); Result := ZeroPad(y, 4) + ZeroPad(m, 2) + ZeroPad(d, 2); end; |
Re: INI-Datei sortieren
Ja, Super, nochmals vielen,vielen Dank.
Doch weiterhin bleibt das Problem, das die INI in ihrer strucktur zwar umsortiert wird aber eben die Einträge ihre Zählöer behalten. Soll heißen ... [123] date=1.1.2004 [456] date=1.1.2003 wird sortiert nach [456] date=1.1.2003 [123] date=1.1.2004 Bei auslesen allerdings ist das völlig egal. Und die Reihenfolge ist somit nicht geändert. Ich habe natürlich bereits versuch da durchzusteigen ... leider ohne Erfolg. Ich krieg das nicht hin. MfG |
Re: INI-Datei sortieren
Du verwirrst mich. Hat die Zahl, die den Abschnitt kennzeichnet, keine Bedeutung? Du willst die einfach neu durchnummerieren? Wenn dabei eventuelle Lücken verschwinden dürfen - nichts leichter als das. Ändere einfach die Zeile mit dem WriteString() aus:
Delphi-Quellcode:
marabu
...
ini.WriteString(IntToStr(Succ(i)), sKey, slSection.Values[sKey]); ... |
Re: INI-Datei sortieren
VIELEN, VIELEN, VIELEN, VIELEN, VIELEN, VIELEN, VIELEN DANK.
So klappts. Das ganze Tool (incl. einer "Gauge" also dieser Fortschrittanzeige) hat jetzt gerade mal 382kb. Und es braucht für mein 2500 Einträge-Test-INI ca 3-4 Sekunden. Nochmals, VIELEN Dank, MfG |
Alle Zeitangaben in WEZ +1. Es ist jetzt 22:46 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