Entwickler-Ecke
Open Source Units - FastIniFiles 3.2
Silas - Fr 31.08.07 16:21
Titel: FastIniFiles 3.2
FastIniFiles (TFIniFile)
Die Klasse TFIniFile hat im Grunde die selbe Funktion wie TIniFile, nur wird die INI-Datei komplett in einen Speicherbaum geladen und von dort aus gelesen/bearbeitet. Die Handhabung ist der von TRegistry relativ ähnlich.
Vorteile:- Es können auch größere Dateien ohne extrem hohen Zeitverbrauch verwendet werden (bis zu 100 mal schneller als TMemIniFile!)
- Es lässt sich feststellen, ob die geöffnete Datei fehlerfrei war
- Es gibt die Möglichkeit, die Datei in einem anderen Ordner / mit einem anderen Dateinamen zu speichern
- FastIniFiles besitzt mehr Möglichkeiten, Daten zu speichern (z.B. Binärdaten)
Beispiel:
Ein Code, der in der Datei "test.ini" aus der Sektion "testSect" die Eigenschaft "testValue" ausliest, könnte folgendermaßen aussehen:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8:
| with TFIniFile.Create('test.ini') do begin if SectionExists('testSect') then begin EnterSection; if ValueExists('testValue') then WriteLn('testValue: ' + ReadString) else WriteLn('Konnte Eigenschaft nicht auslesen'); end else WriteLn('Konnte Sektion nicht finden'); Free; end; |
Speedtest: (Im Vergleich zu
TMemIniFile)
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:
| TMemIniFile vs. TFIniFile Speedtest ===================================
Ergebnisse:
TMemIniFile Create & Free Große Datei: 7,328 ms Mittlere Datei: 2,235 ms Kleine Datei: 0,203 ms Datei auslesen (Mit Prüfung) Große Datei: 339,187 ms Mittlere Datei: 63,312 ms Kleine Datei: 0,797 ms TFIniFile Create & Free Große Datei: 10,766 ms Mittlere Datei: 3,093 ms Kleine Datei: 0,235 ms Datei auslesen (Mit Prüfung) Große Datei: 3,75 ms Mittlere Datei: 0,922 ms Kleine Datei: 0,16 ms
Große Datei = 100 Sektionen a 50 Eigenschaften Mittlere Datei = 50 Sektionen a 30 Eigenschaften Kleine Datei = 5 Sektionen a 10 Eigenschaften
Alle Tests wurden der Genauigkeit halber 1000 mal durchgeführt. |
Lizenz: Die Lizenz liegt der Unit bei.
Gausi - Fr 31.08.07 16:30
Interessante Idee. Kannst du grob erläutern, wo der Vorteil deiner Klasse gegenüber TMemIniFile ist? Denn da wird das ja ähnlich gehandhabt, oder irre ich mich da?
Silas - Fr 31.08.07 17:03
:les: Oh, TMemIniFile hab ich noch gar nicht gekannt. Das macht den größten Vorteil schon einmal zunichte.
Mein zugegebenermaßen nicht so tolles Delphi-Buch sagt mir (mehr oder weniger gut), das das ganze in Stringlisten gespeichert wird (stimmt das?).
Meine Klasse speichert es als Baum, also in etwa so:
Wenn das mit den Stringlisten stimmt, wäre ein Baum schon schneller, weil kopierarbeit wegfällt.
Die "ganze Arbeit" wird bei meiner Klasse im Konstruktor ausgeführt, die Read/Write-Methoden müssen nur noch im Baum den jeweiligen Wert suchen.
Außerdem gibt es (wie bei TRegistry) eine aktuelle Sektion, sodass nicht bei jedem Vorgang die Sektion gesucht werden muss (Ich weiß nicht wie das bei TMemIniFile ist, deswegen geh ich hier von TIniFile aus).
Horst_H - Fr 31.08.07 17:42
Hallo,
eine kleine Frage:
wieso dies hier?
Delphi-Quelltext
1: 2:
| Float1=123.456 #Float mit . Float2=123,456 #Float mit , |
Wäre es nicht geschickter in der Ini Datei den Ländercode mitzuspeichern oder das Format von "Format" mit abzuspeichern??
Gruß Horst
Silas - Fr 31.08.07 18:12
Na ja, man muss immer davon ausgehen, dass in einer INI-Datei (die ja deutsch oder englisch oder was auch immer sein kann) diese Info nicht gespeichert ist. Dann kann der Parser ja nicht wissen, welches Format das verwendete ist.
BenBE - Fr 31.08.07 21:27
Ein paar Fragen:
- Ist das Kommentar-Zeichen einstellbar?
- Könnte der Parser so erweitert werden, dass man Kommentare zurückspeichern kann? (Wär doch schade, wenn meine php.ini plötzlich ohne Kommentare dastände ;-))
- Kommt deine Klasse mit doppelten Sektionen oder doppelten Einträgen klar (Sagen wir, weil ein Programm denkt, mehrzeilige Angaben durch mehrere Zeilen mit dem Gleichen Namen zu speichern?
- Kann man die Reihenfolge der Einträge beeinflussen beim Speichern?
Kennst Du TBigIniFile?
- Kann deine Klasse TColor-Werte lesen?
- Werden andere Zusatztypen unterstützt? (z.B. Sets oder Enums auslesen, wenn man die Typinfo von Delphi mitliefert)???
Ansonsten ne nette Idee; hab mir die Implementierung aber noch nicht im Detail angeschaut.
matze - Fr 31.08.07 21:57
Ja das mit dem Kommentarzeichen ist wichtig. Das muss irgendwie markiert werden.
Denn wenn ich folgenden String abspeichern möchte: Das ist das Haus #4 würde ja nur Das ist das Haus rauskommen. Du müsstest das irgendwie "escapen".
Man müsste auch direkt mal einen Speedtest durchführen: FastIniFiles vs MemIniFile
Silas - So 02.09.07 12:28
BenBE hat folgendes geschrieben: |
Ist das Kommentar-Zeichen einstellbar? |
Ab jetzt schon. :) (Der Konstruktor hat einen zweiten Parameter bekommen)
BenBE hat folgendes geschrieben: |
Könnte der Parser so erweitert werden, dass man Kommentare zurückspeichern kann? |
Schwierig. Das ist ein Nachteil der Baumstruktur. Wenn du die Datei nicht bearbeitest, bleibt sie ja unverändert. Es gäbe die Möglichkeit, für jede Eigenschaft die Kommentare davor bzw. danach abzuspeichern, aber ob dass so effizient ist... Ich werd's mal versuchen, aber wenn jemand eine bessere Idee hat, freu' ich mich natürlich.
BenBE hat folgendes geschrieben: |
Kommt deine Klasse mit doppelten Sektionen oder doppelten Einträgen klar (Sagen wir, weil ein Programm denkt, mehrzeilige Angaben durch mehrere Zeilen mit dem Gleichen Namen zu speichern? |
Auch noch nicht. Aber ich könnte es so ändern, dass er in diesem Fall eine Stringliste verwendet, oder dass es ein Zeilen-Fortsetzungs-Zeichen (wie in manchen Sprachen der Backslash) gibt (Das zweite wäre natürlich einfacher).
BenBE hat folgendes geschrieben: |
Kann man die Reihenfolge der Einträge beeinflussen beim Speichern? |
Nein, das ist wieder ein Problem mit der Baumstruktur. Die neuesten Einträge landen immer unten in der Sektion bzw. in der Datei.
BenBE hat folgendes geschrieben: |
Kennst Du TBigIniFile? |
Nein :wink: (Hab auf die Schnelle jetzt auch nichts gefunden)
BenBE hat folgendes geschrieben: |
Kann deine Klasse TColor-Werte lesen? |
Ist das nicht ein Integer?
BenBE hat folgendes geschrieben: |
Werden andere Zusatztypen unterstützt? |
Bis jetzt nur String, Integer, Boolean und Extended. Werd' aber noch eine
ReadBinary und
WriteBinary-Methode einbauen.
matze hat folgendes geschrieben: |
Man müsste auch direkt mal einen Speedtest durchführen: FastIniFiles vs MemIniFile |
Voilà: Siehe erster Post
Schaut euch das Ergebnis an. :beer:
Silas - Sa 05.01.08 15:16
So, nach einem knappen halben Jahr: Ein neues Release! (Version 2.0)
[+] Read/WriteBinary - Funktionen: Schreiben/Lesen beliebige Werte (z.B. Records, GUIDs) als hexadezimalen string in die/aus der Datei.
[+] Escapede Strings: Schreiben/Lesen nach C-Art escapede Strings ((un)escaped werden die Whitespaces, sodass beispielsweise mehrzeilige und/oder mit Tabs/Leerzeichen formatierte Werte gespeichert werden können
[+] Eine Clear-Prozedur: Löscht den Inhalt der gesamten Datei
[+] Dazu gehörend eine ClearSection-Prozedur: löscht den Inhalt einer Sektion
[+] Zugriffsbeschleunigung: Wenn z.B. die existenz einer Sektion mit SectionExists abgefragt wurde, muss bei EnterSection der Name nicht erneut angegeben werden, da die Klasse nun die Daten (also den Index im Array) des letzten Zugriffs speichert.
[+] Int64: Read/WriteInteger speichert/liest nun Int64-Werte
[*] Die ReadInteger/Bool/Float-Funktionen lösen bei einem Konvertierungsfehler nun keine Exception mehr aus, sondern geben einen Standardwert zurück (0, false, 0.0)
[*] Ein paar unwichtige Optimierungen
[*] Die Exception-Typen EIniSectionNotFound und EIniValueNotFound wurden zu EIniEntryNotFound zusammengefasst.
Ich werde, sobald wie möglich, eine Funktion zum speichern der Kommentare schreiben. Die Formatierungen wie führende Leerzeichen und Leerzeilen (ohne Kommentarzeichen) würde ich dann aber außer Acht lassen.
Silas - Mo 04.02.08 12:22
Nochmal ein Neues Release (Version 2.1):
[+] RenameSection/RenameValue-Funktionen: Benennen Eigenschaften und Funktionen um
[+] WriteString/ReadString escaped wenn auch Kommentarzeichen (zu \c)
[*] Bugfix: Ein Bug, der das Einlesen von gleichnamigen Eigenschaften in verschiedenen Sektionen verhindert hat, wurde behoben
[*] Ein paar unwichtige (Architektur-)Veränderungen
Download im ersten Posting.
Ich schreib gerade an der Kommentar-Funktion, erweist sich allerdings als schwierig.
Gahero - Di 05.02.08 15:35
Geile Sache.
Bin gerade am überlegen, ob ich mein Projekt, was demnächst mal wieder eine Frischzellenkur braucht auf Fastinifiles umzustellen. Gibts noch andere Vorteile außer bessere Geschwindigkeiten bei größeren Datenmengen und speichern von anderen Datentypen?
Silas - Di 05.02.08 16:22
Gahero hat folgendes geschrieben: |
Geile Sache.
Bin gerade am überlegen, ob ich mein Projekt, was demnächst mal wieder eine Frischzellenkur braucht auf Fastinifiles umzustellen. |
Danke. Freut mich sehr.
Gahero hat folgendes geschrieben: |
Gibts noch andere Vorteile außer bessere Geschwindigkeiten bei größeren Datenmengen und speichern von anderen Datentypen? |
- Mehr Bearbeitungsmöglichkeit(en): Eine Rename- und eine Clear-funktion (ich weiß nicht, ob es letztere auch in TIniFile gibt, kann sein)
- Du musst weniger tippen :) (Wegen der Funktion des automatischen letzten Zugriffs)
- FastIniFiles wird weiterentwickelt!
Heiko - Di 05.02.08 18:14
Hallo Silas,
es gibt eine Stelle, dir mir bei OpenSource-Units immer gleich einfällt, wo eine Fehlerstelle ist ;).
Versuch mal eine ini zu öffnen, wo der Pfad folgendermaßen ist ;):
Quelltext
1:
| C:\Нас Не Дагонят\test.ini |
Wie du dort sehen wirst, scheitert deine Unit daran. UniCode-Support wäre also nicht schlecht (ich hab hier in der Sparte ne Unit dafür liegen, falls du die verwenden möchtest. Alternativ kannste ja auch einen constructor für TFile anbieten, so dass er die Daten auch von MemoryStreams annehmen kann).
Silas - Di 12.02.08 20:05
Danke für die Antwort! Die Idee mit den Streams ist interessant, aber der Destruktor muss das Ganze ja wieder speichern können... Soll ich dann einfach dem Destruktor einen Parameter geben, oder wie hast du das gemeint?
Heiko - Di 12.02.08 20:22
Wenn man im constructor einen Stream übergibt, erhält man ja eigentlich nur eine Referenz, mit der du arbeitren kannst. Diese behällst du dir als private-Var in der Klasse. Sobald der destructor aufgerufen wird, verwendest du die einfach weiter. Das birgt zwar ein paar mögliche Fehlerstellen (ein anderer gibt hat die Klasse bereits freigegeben), aber es gibt eben immer Schwachpunkte ;). Du kannst natürlich dem destructor auch eine Variable geben. Nimm einfach das, was dir am besten gefällt.
Silas - Di 12.02.08 20:45
Das war das Problem, das ich gemeint habe. Ich denke, ich werde jetzt erst einmal den Unicode-Support aus deiner Unit (mit internem Stream natürlich) und dann vielleicht einen Read-Only-Modus für Streams schreiben. Lassen sich z.B. Resource-Streams überhaupt schreiben?
Heiko - Di 12.02.08 21:16
Silas hat folgendes geschrieben: |
Ich denke, ich werde jetzt erst einmal den Unicode-Support aus deiner Unit (mit internem Stream natürlich) |
Ich werde die Woche dafür sicherlich ein Update rausbringen, womit das umstellen auf TStream nur noch ein minimaler Compilierschalter ist (habs gerade auf die schnelle probiert, aber Borland nutzt an der einen Stelle Int64, wo ich nur Cardinal nutze, wes wegen ich an ein paar Stellen mehr den Compilierweichen einbauen muss).
Silas hat folgendes geschrieben: |
und dann vielleicht einen Read-Only-Modus für Streams schreiben. |
Wäre eine Möglichkeit. An der Stelle vlt. einen alterativen Destruktor anbeiten, der das auch dann schreiben kann.
Silas hat folgendes geschrieben: |
Lassen sich z.B. Resource-Streams überhaupt schreiben? |
Du meinst bezüglich meiner Unit? Wenn du die auf TStreams basieren lässt wahrscheinlich. Ich habs bisher nicht gebraucht, von daher auch nicht getestet ;).
Silas - Di 12.02.08 22:56
Heiko hat folgendes geschrieben: |
Ich werde die Woche dafür sicherlich ein Update rausbringen, womit das umstellen auf TStream nur noch ein minimaler Compilierschalter ist. |
Ich hätte gedacht das wär schon so? Oder war es gar nicht
die [
http://www.delphi-forum.de/viewtopic.php?t=62275&start=0&postdays=0&postorder=asc], die du gemeint hast?
Heiko hat folgendes geschrieben: |
Silas hat folgendes geschrieben: | Lassen sich z.B. Resource-Streams überhaupt schreiben? |
Du meinst bezüglich meiner Unit? Wenn du die auf TStreams basieren lässt wahrscheinlich. Ich habs bisher nicht gebraucht, von daher auch nicht getestet ;). |
Nein, ich meine
TResourceStream, mit dem man auf Ressourcen zugreifen kann. Ich denke nicht, dass man auf so einen Stream (wirklich) schreiben kann, oder? Schließlich ist die Resource ja in der EXE verankert...
Das mit dem alternativen Destruktor werd ich wahrscheinlich so machen :) .
Heiko - Mi 13.02.08 08:12
Doch die meine ich ;). Wenn ich dich richtig verstanden habe, willst du ja als Grundobjekt nicht TObject haben, sondern TStream. Um beide Variante zu erlauben, kommt demnächst ein Compilierschalter rein, da ich TStrea,m bisher außebn vorgelassen habe.
Silas hat folgendes geschrieben: |
Nein, ich meine TResourceStream, mit dem man auf Ressourcen zugreifen kann. |
Achso, den muss ich mir mal angucken. Ich hab schon eigentlich geguckt, ob in Classes ein weiterer Stream ist, aber den habe ich wohl übersehen ;).
Silas - Mi 13.02.08 17:23
Heiko hat folgendes geschrieben: |
Doch die meine ich ;). Wenn ich dich richtig verstanden habe, willst du ja als Grundobjekt nicht TObject haben, sondern TStream. Um beide Variante zu erlauben, kommt demnächst ein Compilierschalter rein, da ich TStrea,m bisher außebn vorgelassen habe. |
Nein, nein, ich will schon
TObject als Elternklasse lassen, nur den Konstruktor umschreiben, dass er mit Streams arbeitet, und anschließend diesen wieder für Dateien überladen, dass der Parser selbst also nur noch mit Streams arbeitet. Denk ich, wäre sinnvoller, weil ja ein Parser (als Klasse) nicht viel mit Streams am Hut hat und ich sonst die ganzen Read / Write Methoden überladen muss, bloß mit was? :wink:
Heiko - Mi 13.02.08 17:39
Die Streams brucht du doch nur zum Laden bzw. Speichern. Das zeug dazwischen würde ich nicht per Streams machen, da dass eine aufwändige umkopiererrei ist.
PS: Kannst du mal von deinem letzten Post kurz Pseudocode oder ähnliches geben, damit ich weiß, was du meinst? Denn ich sehe da gerade nicht ganz durch, was du genau meinst (oder ich muss ihn mir später nochmal angucken, wenn meine Gedanken von der Schule endgültig erlöst sind :mrgreen:)
Silas - Mi 13.02.08 18:02
Heiko hat folgendes geschrieben: |
Die Streams brucht du doch nur zum Laden bzw. Speichern. Das zeug dazwischen würde ich nicht per Streams machen, da dass eine aufwändige umkopiererrei ist. |
So mein ich des ja :)
Heiko hat folgendes geschrieben: |
PS: Kannst du mal von deinem letzten Post kurz Pseudocode oder ähnliches geben, damit ich weiß, was du meinst? Denn ich sehe da gerade nicht ganz durch, was du genau meinst (oder ich muss ihn mir später nochmal angucken, wenn meine Gedanken von der Schule endgültig erlöst sind :mrgreen:) |
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9:
| type TFIniFile = class private public constructor Create(const Stream: TStream); overload; constructor Create(const FileName: String); overload; end; |
Ich mein, einen Parser von
TStream abzuleiten macht wenig Sinn, weil ein Parser ja kein Stream ist :wink:
Heiko - Mi 13.02.08 21:08
Silas hat folgendes geschrieben: |
Ich mein, einen Parser von TStream abzuleiten macht wenig Sinn, weil ein Parser ja kein Stream ist :wink: |
Ah k, dass meinst du. Mich hatte letztens dieser Satz gestört ;):
Silas hat folgendes geschrieben: |
dass der Parser selbst also nur noch mit Streams arbeitet |
Du meinst also, dass der Dateiconstruktor den Streamconstructor aufruft, nur mit nem selbst erzeugtem Stream. Sag das doch gleich :twisted: .
Silas - Mi 13.02.08 21:54
Heiko hat folgendes geschrieben: |
Silas hat folgendes geschrieben: | dass der Parser selbst also nur noch mit Streams arbeitet |
Du meinst also, dass der Dateiconstruktor den Streamconstructor aufruft, nur mit nem selbst erzeugtem Stream. Sag das doch gleich :twisted: . |
Der Parser selbst
ist ja der Konstruktor... :D
OK ich hab mich vielleicht ein bisschen komisch ausgedrückt :wink:
Silas - So 17.02.08 17:09
So, die neue Version 2.2 ist fertig!
[*] Die Lese- und Schreibmethoden für die Datei arbeiten nun intern mit Streams
[- ] Die SaveAs-Methode fällt weg, dafür akzeptiert Save nun einen Dateinamen-Parameter
[+] Create kann nun auch mit Streams aufgerufen werden
[+] Save kann nun in Streams speichern
[+] Bei ReadBinary kann nun auch der erste Parameter weggelassen werden, das hatte ich vergessen.
[*] Die Unit ist noch ein bisschen schneller geworden :), weil ich für das Einlesen eine Stringliste verwendet hab, die den Vorteil bietet, dass die ganze Datei auf einmal gelesen wird.
(Download im ersten Posting.)
Und es gibt einen neuen Speedtest. Beim Auslese-Test wird nun vorher überprüft, ob der Wert auch existiert. Hier macht sich die Funktion des leztzen Zugriffs deutlich bemerkbar: FastIniFiles ist hier nun bei allen Dateien (klein, mittel, groß) ca. 100 mal schneller als TMemIniFile :!: Außerdem ist in den verschiedenen Dateien auch die Anzahl der Einträge pro Sektion anders. Beim Einlesen liegt TMemIniFile logischerweise weiterhin vorne und ist dort ca. doppelt so schnell.
Das Ergebnis steht nun im ersten Posting, wo ihr den Speedtest auch runterladen könnt. Vorsicht, die neue Version braucht ziemlich viel Zeit, auf meinem (1 x 1.4GHz-) Rechner hat er eine Viertelstunde gedauert.
alzaimar - Di 19.02.08 22:35
Silas hat folgendes geschrieben: |
Und es gibt einen neuen Speedtest. Beim Auslese-Test wird nun vorher überprüft, ob der Wert auch existiert. Hier macht sich die Funktion des leztzen Zugriffs deutlich bemerkbar: FastIniFiles ist hier nun bei allen Dateien (klein, mittel, groß) ca. 100 mal schneller als TMemIniFile :!: |
Also das ist Selbstbetrug. Du testest doch so, das Du einen Wert 1000x liest. Und wenn du das dann optimierst, ist es ja wohl logisch, das dein 'SpeedTest' so ein Ergebnis bringt. Überlege Dir lieber, wie eine Ini-Datei im allgemeinen benutzt wird. Imho werden Werte zufällig gelesen und geschrieben, und nicht 10000x der gleiche Wert.
Bei der Gelegenheit wäre es interessant, den Quelltext von deinem Speedtest zu veröffentlichen. Mal sehen, wie TBigIni da abschneidet.
Silas - Mi 20.02.08 14:47
Das habe ich ja nicht optimiert. Der Geschwindigkeitsvorteil von FastIniFiles liegt zwischen ValueExists und ReadValue, und nicht zwischen zwei Lesevorgägen. ValueExists sucht den Wert immer neu, egal auf welchen vorher zugegriffen wurde. Das ist von praktischem Nutzen, weil man zumindest wenn man sauber programmiert, überprüfen sollte, ob ein Wert vorhanden ist, bevor man ihn benutzt. Die Unit ist hier bei 1000 verschiedenen Werten genauso schnell wie bei 1000 gleichen (zumindest relativ zu TMemIniFile, weil die Dateigröße ja steigen würde).
Der Quelltext liegt dem Speedtest, den du im ersten Posting runterladen kannst, schon bei.
alzaimar - Mi 20.02.08 17:26
silas: Ash on my Haupt.
Silas - Sa 29.03.08 15:45
Moin zusammen! :wave:
Es gibt (mal wieder) ein "Zwischenrelease" zum "großen" FastIniFiles 3.0, bei dem Unicode und Kommentare implementiert sein werden. 3.0 ist schon recht weit, aber noch lange nicht fertig. Diese Version ist daher haupsächlich ein Bugfixrelease.
Zusammen mit diesem Release habe ich auch Versionsnummern für die Unit eingeführt.
Neue Version 2.3
[+] Es gibt nun ReadValueDef-Methoden für alle Lesevorgänge , die bei einem nichtexistierenden Wert oder einem Konvertierungsfehler einen Defaultwert zurückgeben
[*] Ein Bug, der u.U. das schreiben einer nichtexistierenden Datei verhinderte, wurde behoben
[*] Ein weiterer Bug, der u.U. das korrekte Lesen eines Strings verhinderte, wurde ebenfalls behoben
Ich freu' mich natürlich weiterhin über Feedback :)
Silas - Sa 05.04.08 19:57
So, da ist sie:
Version 3.0
[+] Der Parser speichert nun Kommentare sowie Leerzeilen zurück
[*] Der Code wurde ein wenig überarbeitet
[+] Der Quelltext hat die 1000-Zeilen-Marke überschritten ;)
Die Unicode-Unterstützung konnte ich leider noch nicht fertigstellen, da es noch ein Problem mit
Heikos Unicode-Unit gibt. Die wichtigste Änderung ist aber geschehen, deswegen denke ich, 3.0 ist gerechtfertigt.
Dafür habe ich mir aber "Typsicherheit" (a la
name:type=value) in mein TODO geschrieben. Das wäre die erste Veränderung, die den INI-Standard "sprengen" würde, mal sehen, wie ich das implementiere :)
Gahero - So 06.04.08 21:44
Ich bin leider noch nicht dazu gekommen, sie in mein Projekt einzubauen, hab ne ganze Menge anderes Zeug um die Ohren im Moment, aber demnächst werde ich das wohl angehen.
Meinen Respekt haste, weiter so... Wenn das Teil demnächst mehr sinnvolle und vorallem neue Features hat, die man nicht standardmäßig hat, wirds vllt auch mehr Leute interessieren die hier posten...
Silas - Mo 07.04.08 14:39
Gahero hat folgendes geschrieben: |
Meinen Respekt haste, weiter so... |
Vielen Dank!
Gahero hat folgendes geschrieben: |
Wenn das Teil demnächst mehr sinnvolle und vorallem neue Features hat, die man nicht standardmäßig hat, wirds vllt auch mehr Leute interessieren die hier posten... |
Freilich bemühe ich mich immer, neue Features einzubauen (wenn mir welche einfallen). Das Problem ist nur: Wenn mir niemand Vorschläge macht, was ich denn verbessern könnte, dauert es natürlich wesentlich länger, bis es etwas neues gibt.
Gahero - So 27.04.08 10:57
Habe jetzt endlich mal angefangen die Unit in mein Proj einzubauen.
Ich benutzte folgenden Code für meine Sprachdateien: (nur ein Auszug, der Rest ist ähnlich aufgebaut)
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:
| with TFIniFile.Create(ExtractFilePath(ParamStr(0)) + 'data/lang/lang_new.ini') do begin
for i := 1 to Frm.ComponentCount - 1 do begin
compo := Frm.Components[i];
if (compo is TLabel) then begin Entersection('TLabel'); WriteString((compo as TLabel).Name, (compo as TLabel).Caption); end;
if (compo is TBitBtn) then begin Entersection('TBitBtn'); WriteString((compo as TBitBtn).Name, (compo as TBitBtn).caption); end;
end;
Free;
end; |
Nachdem ich den Code für FastIniFile umgebaut habe, bringt er mir allerdings jedes Mal, wenn ich den Code oben aufrufe folgenden Fehler:
Zugriffsverletzung. (in der Zeile 621 " if Length(Value) > 0 then begin" Prozedure Save) Vorher mit TIniFile hat noch alles geklappt. Ist mein Code falsch oder hab ich nen Bug gefunden?
Silas - So 27.04.08 19:41
Moin Gahero,
werde mir das Problem morgen mal ansehen...
Bist du sicher, dass du die letzte Version (3.0, vom 5. April) verwendest? Ich kann mich dunkel daran erinnern, so etwas gefixt zu haben. Dein Quelltext an sich ist soweit fehlerfrei (und der Fehler tritt ja in meiner Unit auf).
Gahero - So 27.04.08 19:54
Hi,
habe die neuste Version 3.0. Ich habe oben auch noch den ersten kommentierten Code ausprobiert, der klappt ohne Probleme...
Silas - Mo 28.04.08 21:12
Ich habe den Bug gefunden und soweit behoben, allerdings ist er bei mir an einer anderen Stelle aufgetreten (was u.U. mit der Bereichsprüfung zusammenhängt).
Für diesen minimalen Fix spare ich mir eine Versionsnummer, sie ist weiterhin 3.0. :wink:
Die Projekt-Zip ist aktualisiert, du kannst sie im ersten Posting runterladen.
Gahero - Di 29.04.08 12:19
Ok, also mit der gefixten Version geht es ohne Probleme. Vielen Dank für das schnelle Update!
Regan - Do 08.05.08 19:59
Silas hat folgendes geschrieben: |
Freilich bemühe ich mich immer, neue Features einzubauen (wenn mir welche einfallen). Das Problem ist nur: Wenn mir niemand Vorschläge macht, was ich denn verbessern könnte, dauert es natürlich wesentlich länger, bis es etwas neues gibt. |
Dann versuch ich hier mal meine Vorschläge mit einzubeziehen: Wie wäre die Funktion, dass, wenn man eine Sektion geöffnet hat, man alle Werte auslesen kann.
Ansonsten funktioniert deine Unit sehr gut. Ich bin voll und ganz zufrieden :zustimm: .
Silas - Do 08.05.08 22:36
Regan hat folgendes geschrieben: |
Wie wäre die Funktion, dass, wenn man eine Sektion geöffnet hat, man alle Werte auslesen kann. |
Gute Idee. Was hast du dir denn so als Ziel fürs Auslesen vorgestellt? Eine Stringlist (bzw. ein TStrings) oder eher ein String- oder gar ein Variant-Array?
Vielleicht könnte man in dieser Methode auch noch eine Filterfunktion einbauen.
Regan hat folgendes geschrieben: |
Ansonsten funktioniert deine Unit sehr gut. Ich bin voll und ganz zufrieden :zustimm: . |
Vielen Dank, freut mich.
Regan - Fr 09.05.08 10:58
Silas hat folgendes geschrieben: |
Regan hat folgendes geschrieben: | Wie wäre die Funktion, dass, wenn man eine Sektion geöffnet hat, man alle Werte auslesen kann. | Gute Idee. Was hast du dir denn so als Ziel fürs Auslesen vorgestellt? Eine Stringlist (bzw. ein TStrings) oder eher ein String- oder gar ein Variant-Array?
Vielleicht könnte man in dieser Methode auch noch eine Filterfunktion einbauen. |
Das würde ich eigentlich dir überlassen. Aber eine StringList mit den Namen würde
mir eigentlich schon zureichen.
Silas - Fr 09.05.08 12:54
Regan hat folgendes geschrieben: |
Aber eine StringList mit den Namen würde mir eigentlich schon zureichen. |
Ach so, ich hätte gedacht du meinst nicht die Namen, sondern die Werte. Das kommt auf jeden Fall mal so rein, vielleicht auch noch Methoden fürs Auslesen der Werte, mal sehen, ob mir was ordentliches einfällt. :)
Regan - Fr 09.05.08 16:08
Silas hat folgendes geschrieben: |
Regan hat folgendes geschrieben: | Aber eine StringList mit den Namen würde mir eigentlich schon zureichen. |
Ach so, ich hätte gedacht du meinst nicht die Namen, sondern die Werte. Das kommt auf jeden Fall mal so rein, vielleicht auch noch Methoden fürs Auslesen der Werte, mal sehen, ob mir was ordentliches einfällt. :) |
Nur nochmal zur Absicherung:
Ini hat folgendes geschrieben: |
[testSection]
testName=testWert
|
Die meine ich :wink: .
Heiko - Fr 09.05.08 19:29
Hallo Silas,
kannst bitte in dem Threadtitel die aktuelle Versionsnummer mit einbauen? Denn bei Thunderbird denke ich immer: "nicht schon wieder nen Post dort", wenn dagegen auf einmal ne neue Versionsummer auftaucht, denke ich immer: "Ah mal schaun, was es neues gibt" :mrgreen: .
Silas - Fr 09.05.08 22:36
Regan hat folgendes geschrieben: |
Nur nochmal zur Absicherung:
Ini hat folgendes geschrieben: | [testSection]
testName=testWert
|
Die meine ich :wink: . |
Gut. Ich auch ;) .
Heiko hat folgendes geschrieben: |
kannst bitte in dem Threadtitel die aktuelle Versionsnummer mit einbauen? |
Bitteschön! ;)
Silas - Di 13.05.08 17:08
Dieses Release ist doch deutlich dicker geworden, als ich es ursprünglich geplant hatte. Das Feature mit der Werteliste habe ich auch auf Sektionen ausgedehnt, und in Verbindung damit könnt ihr auf die Einträge auch über Indizes zugreifen (Das gilt sowohl für
EnterSection als auch für
ReadValue und
DeleteEntry). Die Funktion zum Wiederherstellen einzelner Einträge könnte für den einen oder anderen ganz interessant sein, der alle Werte bis auf einige wenige löschen will.
Neue
Version 3.1
[+] Es gibt nun die Möglichkeit, die Sektions- und Wertenamen in eine Stringliste zu exportieren
[+] Im Zusammenhang ist es nun möglich, sowohl die Sektionen als auch die Werte mit Indizes anzusprechen
[*] Ein Bug in den Binary-En/Decode-Methoden wurde beseitigt (Danke @
BenBE)
[+] Im Destruktor kann jetzt angegeben werden kann, ob Änderungen gespeichert werden sollen
[+] Gelöschte Sektionen und Werte können wiederhergestellt werden.
[*] Ein Bug, der
Empty falsch zurückgegeben hat, wurde gefixt
[+] Die betretene Sektion kann jetzt verlassen werden (hat im Moment noch nicht viel Sinn)
[*] Und noch ein paar unwichtige Änderungen
Regan - Di 13.05.08 20:43
Silas hat folgendes geschrieben: |
Dieses Release ist doch deutlich dicker geworden, als ich es ursprünglich geplant hatte. Das Feature mit der Werteliste habe ich auch auf Sektionen ausgedehnt, und in Verbindung damit könnt ihr auf die Einträge auch über Indizes zugreifen (Das gilt sowohl für EnterSection als auch für ReadValue und DeleteEntry). Die Funktion zum Wiederherstellen einzelner Einträge könnte für den einen oder anderen ganz interessant sein, der alle Werte bis auf einige wenige löschen will.
|
Da bringt mir die neue Version ja gleich doppelt etwas. Sehr gut :zustimm: .
Silas - So 18.05.08 14:31
Regan hat folgendes geschrieben: |
Sehr gut :zustimm: . |
Vielen Dank! Da schieb ich doch gleich noch ein Release nach: :)
Version 3.2
[+] Die Unit arbeitet jetzt mit einer eigenen, schnelleren Char-Pos-Funktion
[+] Die
Read-/
WriteBinary-Methoden arbeiten jetzt auch mit Streams
[*] Alle Assembler-Methoden wurden überarbeitet
[*] Ein Fehler, der bei
Read-/
WriteBinary Probleme mit einigen Bytecodes verursacht hat, wurde behoben
[+] Der Parser/Writer arbeitet jetzt mit einem
MemoryStream als Zwischenspeicher
[+] Stringlisten (
TStrings) lassen sich nun über
ReadStringList/
WriteStrinList lesen/schreiben
[+] WriteValue-Methoden akzeptieren jetzt ebenfalls Indizes
[*] Die Read-/WriteBool-Methoden verwenden nun Standardmäßig Boolean-Strings ('true', 'false') anstatt von 0 und 1
[*]
WriteFloat schreibt Floats jetzt standardmäßig mit '.' als DecimalSeparator
Mit dem Stream-Handling haben jetzt alle Geeks unter euch, die schon immer mal Screenshots und DVD-Rips in INIs speichern wollten, endlich die Möglichkeit dazu ;).
Die Boolean-Methoden sind trotz dem, dass sie ab jetzt Strings schreiben, zu 0 und 1 abwärtskompatibel. Bei der Erkennung true/false wird, wie unter C üblich, alles, was nicht false ist, als true angenommen.
Natürlich freu' ich mich weiterhin über Feedback :)
Regan - So 18.05.08 14:37
Mir ist noch was aufgefallen: Bei der procedure ListValues, könntest du da bitte als ersten Parameter auch eine Sektion angeben, sonst muss ich die immer vorher aufrufen?
Silas - So 18.05.08 19:48
Regan hat folgendes geschrieben: |
Bei der procedure ListValues, könntest du da bitte als ersten Parameter auch eine Sektion angeben, sonst muss ich die immer vorher aufrufen? |
Hm, ich glaube, das würde mir mein Konzept ein wenig durcheinanderwerfen :? . Das ist doch auch nur eine Zeile mehr.
Für welchen Zweck brauchst du's denn? Wenn man eine Werteliste abruft, dann doch meistens, um nachher darauf zuzugreifen.
Gahero - So 18.05.08 20:24
Ich würde das so lassen, da grenzt du dich mehr von der normalen TInifile noch mehr ab und der Code wird (finde ich) übersichtlicher. Die neuen Features sind echt gelungen, das kann ich gut gebrauchen... Weiter so.
BenBE - So 18.05.08 20:57
Könnte man doch mit drei Befehlen machen:
1. einer ohne Parameter (aktuelle Sektion)
2. per Index (öffnet die Sektion intern, ruft die parameterlose Version auf und schließt die Sektion nachher wieder)
3. per Name (halt wie 2., nur mit Name statt Index zur Identifikation der Sektion)
Damit sollte jeder seinen Lieblingsweg haben.
Silas - So 18.05.08 21:41
Gahero hat folgendes geschrieben: |
Ich würde das so lassen, da grenzt du dich mehr von der normalen TInifile noch mehr ab und der Code wird (finde ich) übersichtlicher. |
Ich finde auch, dass die Änderung hier nicht wirklich sinnvoll ist, weil sie keine neue Funktionalität enthält und damit IMHO zu einem schlechten Design führt.
Gahero hat folgendes geschrieben: |
Die neuen Features sind echt gelungen, das kann ich gut gebrauchen... Weiter so. |
Vielen Dank! Werd mich bemühen. :)
BenBE hat folgendes geschrieben: |
Könnte man doch mit drei Befehlen machen:
1. einer ohne Parameter (aktuelle Sektion)
2. per Index (öffnet die Sektion intern, ruft die parameterlose Version auf und schließt die Sektion nachher wieder)
3. per Name (halt wie 2., nur mit Name statt Index zur Identifikation der Sektion) |
So hätte ich das denke ich auch gelöst.
@
Regan: In welchem Zusammenhang bzw. warum lässt du eine Werteliste erstellen ohne nachher auf die Werte zuzugreifen? Wie sieht in dem Fall das Design-Konzept von deiner INI aus?
Regan - Di 20.05.08 17:22
Silas hat folgendes geschrieben: |
@Regan: In welchem Zusammenhang bzw. warum lässt du eine Werteliste erstellen ohne nachher auf die Werte zuzugreifen? Wie sieht in dem Fall das Design-Konzept von deiner INI aus? |
Ic glaube ich habe mich da etwas falsch ausgedrückt. Ich wollte noch
zusätzlich den Parameter
Sectionname.
Also dann so:
procedure ListValues(const nName: String; Dest: TStrings);.
Sonst muss ich vorher immer die Section betreten. Das ist aber manchmal echt
bescheuert sehr ungünstig, da ich manchmal nur einen Wert abfragen will, oder, wie bei ListValues, nur die Werte auslesen will und im Endeffekt in dem weiteren Codeabschnitt nichts mehr damit anfange.
Ich hoffe das war verständlicher ausgedrückt.
Silas - Di 20.05.08 18:28
Hm...
Ohne Änderung
1: 2: 3: 4: 5:
| for i := 0 to 255 do if SectionExists('MySection' + IntToStr(i)) then begin EnterSection; ListValues(MySectionValues[i]); end; |
Mit Änderung
1: 2: 3:
| for i := 0 to 255 do if SectionExists('MySection' + IntToStr(i)) then ListValues('MySection' + IntToStr(i), MySectionValues[i]); |
Wo ist beim ersten Code der Mehraufwand? :gruebel: Es fällt gerade mal ein
begin-
end-Block raus.
Code- oder Geschwindigkeitstechnisch würde sich auch nichts ändern, weil diese Version einfach nur die Aufrufe nacheinenader ausfürhen würde... Bin mir jetzt aber nicht sicher, ob ich dein Problem richtig verstanden hab. :nixweiss:
Vielleicht noch ein Tipp zur Strukturierung einer INI:
Ich hab mir da eine Methode angewöhnt, mit der ich eigentlich immer recht zufrieden bin. Die Sektionen sind immer eindeutig einer Funktion zugeordnet, eine z.B. für die Einstellungen, eine als "Datenbank", usw. Die meinsten meiner INIs haben deswegen auch nur eine einzige Sektion.
Die Werte leg ich immer im "OOP-Style" an, d.h. bei mehreren, durchnummerierten a la
<Nummer>.[<Kategorie>.]<Wertname> .
Ein Beispiel
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14:
| [items] count=3 0.id=57a3e1425 0.name=myitem1 0.pos.left=20 0.pos.top=15 1.id=f9f2315ab 1.name=myitem2 1.pos.left=35 1.pos.top=10 2.id=a163c057d 2.name=myitem3 2.pos.left=85 2.pos.top=110 |
So lässt sich der Inhalt auch recht schnell und sauber in schleifen auslesen.
Hendi48 - Mi 10.09.08 19:16
Ich kann die Unit in Delphi 2009 nicht compilen :(
Es scheitert an der Funktion CharPos, Zeile 1470:
[DCC Fehler] FastIniFiles.pas(1470): E2107 Operandengröße stimmt nicht überein
Ich glaube da wurde was für Unicode Support geändert..
BenBE - Mi 10.09.08 19:19
Versuch mal
Quelltext
1:
| MOV AL, BYTE PTR [Chr] |
Hendi48 - Mi 10.09.08 19:55
Danke, so geht es!
dummzeuch - Mi 10.09.08 20:38
Eine Funktion, die ich fuer .ini Files haeufiger brauche, ist der Vergleich von zwei Dateien. Prinzipiell ginge das auch mit einem File-Differ, aber leider funktioniert das nur, wenn sich die Reihenfolge der Eintraege nicht geaendert hat.
Kann man vielleicht mit Deiner Klasse die Eintraege in einer bestimmten Reihenfolge abspeichern, so dass man zwei .ini Files damit in eine vorgegebene Reihenfolge bringen kann, um sie anschliessend zu vergleichen?
(Oder kennt vielleicht jemand ein Tool, was zwei .ini Files vergleicht?)
Heiko - Mi 10.09.08 20:45
ToroiseSVN kann Textdateien vergleichen. Und nix weiter ist ja eine INI. Probier es mal damit. Vlt reicht es dir (sortieren tut der natürlich nicht).
BenBE - Mi 10.09.08 21:15
Dann sollte er aber nicht TortoiseMerge nehmen, sondern WinMerge; der erkennt auch verschobene Blöcke korrekt.
Heiko - Mi 10.09.08 21:25
Möglich. Ich habe TortioseSVN oben aber WinMerge nicht (zu mindestens nicht bewusst). Von daher habe ich mit letzterem keine Erfahrung. Auf jeden Fall wäre die Erkennung von verschobene Blocks brauchbar.
Ansonsten: Ich würde ein INI-Vergleich nicht in die Unit einbauen. Das ist zu spezifisch und könnte eigentlich auch mit einem beliebigen Textmerger erreicht werden.
Boldar - Mi 10.09.08 21:26
Heiko hat folgendes geschrieben: |
Ansonsten: Ich würde ein INI-Vergleich nicht in die Unit einbauen. Das ist zu spezifisch und könnte eigentlich auch mit einem beliebigen Textmerger erreicht werden. |
Naja, wenn aber die Reihenfolge anders ist??
Heiko - Mi 10.09.08 21:30
Wie BenBE es sagte: probier WinMerge. Gute Merger erkennen umsortierung ;).
dummzeuch - Do 11.09.08 15:01
Heiko hat folgendes geschrieben: |
ToroiseSVN kann Textdateien vergleichen. Und nix weiter ist ja eine INI. Probier es mal damit. Vlt reicht es dir (sortieren tut der natürlich nicht). |
s.o. ohne Sortieren hilft es nicht. Programme zum Vergleichen von Textdateien gibt es wie Sand am Meer, ich bevorzuge BeyondCompare.
twm
Gahero - So 12.10.08 14:48
Hallo,
ich bins nochmal.
Ich glaube ich habe noch einen Fehler gefunden.
Kann es sein, dass es manchmal vorkommt, dass ein vorhandener Eintrag nicht richtig ausgelesen wird?
Ich benutze in meinem Programm mehrmals folgenden Code, natürlich mit anderen Eintragsnamen:
Delphi-Quelltext
1:
| Frm.Com_Gamesettings_Vegetation_Quality.ItemIndex := ini_useroptions.ReadInteger('VegetationQuality'); |
Allerdings kommt es manchmal vor, dass immer wieder dieselben Aufrufe bestimmter Eintragsnamen eine 0 zurückliefern, obwohl die entsprechenden Einträge in der ini existieren und einen von 0 verschiedenen Wert besitzen und die anderen Werte korrekt ausgelesen werden. Seltsam ist, dass es immer nur dieselben Einträge sind, bei denen dies geschieht.
Folgende Zeilen sind betroffen:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8:
| ini_useroptions.WriteInteger('TextureQuality', Frm.Com_Gamesettings_Textures_Quality.ItemIndex + 1);
ini_useroptions.WriteInteger('ShadowQuality', Frm.Com_Gamesettings_Shadow_Quality.ItemIndex);
ini_useroptions.WriteInteger('VegetationQuality', Frm.Com_Gamesettings_Vegetation_Quality.ItemIndex); |
Wie schon gesagt, sind es nur diese Zeilen während folgende Zeilen den Fehler noch nie hatten:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13:
| ini_useroptions.WriteString('Resolution.Width', Frm.Edi_Gamesettings_General_ResolutionWidth.Text);
ini_useroptions.WriteString('Resolution.Height', Frm.Edi_Gamesettings_General_ResolutionHeight.Text);
ini_useroptions.WriteString('Resolution.RefreshRate', Frm.Edi_Gamesettings_General_ResolutionRate.Text);
ini_useroptions.WriteInteger('Speaker', Frm.Com_Gamesettings_General_Sound.ItemIndex + 1);
ini_useroptions.WriteString('ShaderQuality', Frm.Com_Gamesettings_Textures_Shader.Text);
ini_useroptions.WriteInteger('TextureFilter', Frm.Com_Gamesettings_Textures_Filtering.ItemIndex); |
Also müsste der Fehler in der Unit von dir liegen, ich hoffe du kannst da was machen... (Oder irgendjmd sonst hier hat eine Idee?)
Bis dann,
GaHero
Moderiert von matze: Delphi-Tags hinzugefügt
Silas - So 12.10.08 17:10
Hi Gahero,
sieht aus, als würde ich doch noch mal aus dem .NET-Paradies zurückkehren :)
Der Fehler kommt mir irgendwie eigenartig vor, vor allem, weil ja alle Werte gleich ausgelesen/geschrieben werden... Vielleicht hast du irgendwo einen Schreibfehler bei einem Sektionsnamen (Groß/Kleinschreibung)? Ansonsten bin ich jetzt leicht überfragt, mir ist sowas noch nie passiert; vielleicht kann ich dir weiterhelfen, wenn du mir Unit & Ini schickst.
Grüße
Silas
Gahero - So 12.10.08 17:58
Ja, ich bin mittlerweile auch bei Net angekommen (ach ich liebe c sharp und visual studio), aber ich habe keine Lust die Anwendung nach Net umzuschreiben, da frag ich lieber dich, ob du da was machen kannst...^^
Hier die beiden Dateien... Wenn du noch was brauchst, sag bescheid!
Gahero - Sa 25.10.08 18:24
Und gibts was neues zu meinen Problem???
TDS - Do 26.03.09 23:15
Hallo @ all :-)
Gibt es denn noch irgendwo eine Möglich für den Download?
silas-online.de (hosted von bplaced.net) ist leider offline :-(
glotzer - So 12.04.09 18:29
hab das selbe problem, und ich würd die fastinis schon gern verwenden :)
TDS - So 12.04.09 19:55
glotzer hat folgendes geschrieben : |
hab das selbe problem, und ich würd die fastinis schon gern verwenden :) |
Hab mal einen Mirror online gestellt soweit ich das aus dem Google Cache holen konnte...
http://home.arcor.de/smartprog4u/
glotzer - So 12.04.09 19:57
tausend dank
himitsu - So 22.11.09 15:34
Mein Fazit zu dieser Klasse:
Solange wie der Ersteller diese nicht grundlegend überholt, ist sie absolut nicht empfehlenswert.
- das Chaos in den Destruktoren (Free ist kein Destructor)
- die Speicherlecks (fast keines der erstellen Objekte wird jemals freigegeben
- ab Delphi 2009 funktioniert keiner seiner ASM-Codes mehr,
da alles auf String/PChar/Char ausgelegt ist, was ab da ja wohl Unicode sein wird
und die ASM-Codes nur auf ANSI laufen. (wenn er wenigstens AnsiString/PAnsiChar und AnsiChar genommen hätte)
Quelle + genauere Gründe:
Delphi-PRAXiS >
FastIniFiles Memory Leaks [
http://www.delphipraxis.net/topic169018.html]
himitsu - So 22.11.09 19:38
- hoffentlich alle Speicherlecks behoben
- nebenbei unicodetauglich gemacht
bezüglich des Unicodes: entweder die INI ist schon Unicode oder man stellt ini.Unicode um
Wehe einer sagt was *speziell bestimmte DPler anguck*
und ja, ich weiß daß ich verrückt bin :nut:
TDS - Mo 23.11.09 09:38
himitsu hat folgendes geschrieben : |
- hoffentlich alle Speicherlecks behoben
- nebenbei unicodetauglich gemacht
bezüglich des Unicodes: entweder die INI ist schon Unicode oder man stellt ini.Unicode um
Wehe einer sagt was *speziell bestimmte DPler anguck*
und ja, ich weiß daß ich verrückt bin :nut: |
So, es wurde gerade alles auf den aktuellen Stand gebracht und erstmal hochgeladen.
http://home.arcor.de/smartprog4u/ ist up2date.
himitsu - Mo 23.11.09 11:45
Ein anderer User (API) hatte sich die Mühe gemacht und das Ganze einer gewissen Style-Guide-Anpassung unterzogen ... also Vieles etwas umformatiert.
Hab die Änderungen im vorhergehenden Post mit einfließen lassen.
[edit]
In der ZIP wurde nun auch die Dokumentation.html um die isUnicode-Eigenschaft erweitert.
Entwickler-Ecke.de based on phpBB
Copyright 2002 - 2011 by Tino Teuber, Copyright 2011 - 2024 by Christian Stelzmann Alle Rechte vorbehalten.
Alle Beiträge stammen von dritten Personen und dürfen geltendes Recht nicht verletzen.
Entwickler-Ecke und die zugehörigen Webseiten distanzieren sich ausdrücklich von Fremdinhalten jeglicher Art!