Unterschied TMemIniFile 10.2 Tokyo / 10.3 Rio
Hallo zusammen,
einige Funktionen in TMemIniFile laufen unterschiedlich zwischen 10.2 Tokyo und 10.3 Rio. z.B. ReadSectionValues und EraseSection In 10.2 wird immer nur eine Section eingelesen und zurückgeliefert (ReadSectionValues), bei 10.3 Rio wird die komplette IniDatei mit allen Sections zurückgeliefert. EraseSection löscht in 10.2 auch nur eine Section, in 10.3 alle Sections in der Ini Datei. Problem ist, dass in meiner Ini Datei der Section-Name mehrmals vorkommt. Also mehrere Sections mit dem gleichen Namen. Gibt es dafür in 10.3 irgendwelche Funktionen, die das gleiche Verhalten wie unter 10.2 liefern oder muss ich mein QT jetzt überall anpassen? Gefunden habe ich so schnell nichts im Sourcecode von 10.3. |
AW: Unterschied TMemIniFile 10.2 Tokyo / 10.3 Rio
Dann hast du dich bisher auf eine fehlerhafte Implementierung verlassen.
Bei Inidateien gibt es die Regel: - Jede Sektion darf nur einmal vorkommen. |
AW: Unterschied TMemIniFile 10.2 Tokyo / 10.3 Rio
ok danke. Dann werde ich das entsprechend anpassen.
|
AW: Unterschied TMemIniFile 10.2 Tokyo / 10.3 Rio
In 10.3 wurde die Performance deutlich gesteigert. Es wird nun ein Dictionary für die Sektionen usw. benutzt (was die Eindeutigkeit voraussetzt).
Windows selbst hat damals zu Zeiten der massenhaften INI-Dateien dann solche Sektionen mit Indizes versehen, z.B. [Section1], [Section2], ... und dazu gab es zumindest teilweise eine Verwaltungssektion mit der Anzahl. |
AW: Unterschied TMemIniFile 10.2 Tokyo / 10.3 Rio
Zitat:
Zitat:
|
AW: Unterschied TMemIniFile 10.2 Tokyo / 10.3 Rio
Zitat:
Gibt es diese Regel wirklich? Ich konnte nie irgendwelche Regeln von Irgendjemand finden. Wikipedia sagt bspw: Zitat:
(Hervorhebung durch mich) Demnach wäre eine Ini-Datei mit mehreren gleichnamigen Sektionen nicht fehlerhaft. Und die Änderung von 10.2 auf 10.3 wäre eine Verhaltensänderung. |
AW: Unterschied TMemIniFile 10.2 Tokyo / 10.3 Rio
|
AW: Unterschied TMemIniFile 10.2 Tokyo / 10.3 Rio
Grundsätzlich geht es (wie fast immer) um die Eindeutigkeit.
Eindeutig muss hier die Kombination aus Sektion und Schlüssel sein, oder welchen Wert würde man von dieser INI erwarten
Code:
wenn man Sektion1 und Schlüssel1 abfragt?
[Sektion1]
Schlüssel1=Wert1 [Sektion2] Schlüssel1=Wert2 [Sektion1] Schlüssel1=Wert3 Allerdings sehe ich (logisch) kein Problem, wenn eine Sektion doppelt auftaucht
Code:
ist halt nur unübersichtlich für den menschlichen Betrachter und wäre so schöner und kompakter
[Sektion1]
Schlüssel1=Wert1 [Sektion2] Schlüssel1=Wert2 [Sektion1] Schlüssel2=Wert3
Code:
IMHO Könnte man beim Lesen diese zerfledderten Sektionen berücksichtigen/zulassen.
[Sektion1]
Schlüssel1=Wert1 Schlüssel2=Wert3 [Sektion2] Schlüssel1=Wert2 |
AW: Unterschied TMemIniFile 10.2 Tokyo / 10.3 Rio
Es gibt viele Implementierungen, die auch mit fehlerhaften INI-Dateien zurecht kommen oder auch fehlerhafte erstellen.
Die Definition dessen, was in INI-Dateien (für gewöhnlich) zulässig ist und was nicht, kann man hier ganz gut nachlesen: https://github.com/SemaiCZE/inicpp/w...-specification https://mozilla-services.readthedocs.../confspec.html https://tech-insider.org/windows/res...0221/1INIW.pdf |
AW: Unterschied TMemIniFile 10.2 Tokyo / 10.3 Rio
Hallo,
Zitat:
Ich erinnere an die Einführung von TStringList.StrictDelimiter, um die alte, "fehlerhafte" (?) Implementierung und vor allem die Anwendungen nicht zu brechen. Wenn TMemIniFile früher falsch implementiert war, gut (oder auch nicht). Aber das Verhalten einer Komponente, was sie seit Äonen (*übertreib*) hat, einfach zu ändern, tztz. |
AW: Unterschied TMemIniFile 10.2 Tokyo / 10.3 Rio
Zitat:
Es steht ja auch an genügend Stellen das Sektionen Eindeutig sein müssen. |
AW: Unterschied TMemIniFile 10.2 Tokyo / 10.3 Rio
Zitat:
Delphi-Quellcode:
(ein reiner Wrapper der Windows-API-Aufrufe) exakt so funktioniert, wie der TE das wünscht. Diese "fehlerhafte" Implementierung wird also vom OS vorgegeben. Richtiger ist die Rio Implementierung von
TIniFile
Delphi-Quellcode:
, allerdings funktioniert diese eben anders als
TMemIniFile
Delphi-Quellcode:
.
TMemIniFile
|
AW: Unterschied TMemIniFile 10.2 Tokyo / 10.3 Rio
Zitat:
Hier steht aber: Note: On Windows, a related object, TMemIniFile, works the same way as TIniFile, but buffers writes in memory to minimize disk access. |
AW: Unterschied TMemIniFile 10.2 Tokyo / 10.3 Rio
Zitat:
http://docwiki.embarcadero.com/Libra...es.TMemIniFile |
AW: Unterschied TMemIniFile 10.2 Tokyo / 10.3 Rio
Dann ist es also doch eine Verhaltensänderung und die ist sogar dokumentiert
Ich finde ein Update sollte kompatibel sein. |
AW: Unterschied TMemIniFile 10.2 Tokyo / 10.3 Rio
Zitat:
Wie würdest du mit WinAPI-Mitteln eine Ini-Datei mit mehreren gleichen Sektionen auslesen können? AFAIK gibt es da keine APIs welche das können würden. |
AW: Unterschied TMemIniFile 10.2 Tokyo / 10.3 Rio
Hm, guter Aspekt. Allerdings habe ich das folgende so verstanden, also ob das ginge.
Zitat:
Zitat:
Ich bin eh der Meinung es gibt keine offizielle Ini-Spezifikation, also eine Norm. |
AW: Unterschied TMemIniFile 10.2 Tokyo / 10.3 Rio
Also damit wir alle über die gleiche Problematik sprechen:
Delphi-Quellcode:
Unter Tokyo
program MemIniTest;
{$APPTYPE CONSOLE} {$R *.res} uses System.Classes, System.SysUtils, System.IniFiles, System.IOUtils; procedure CheckIniClass(AIniFactory: TFunc<string, TCustomIniFile>); const C_CONTENT = '' + // '[S1]' + sLineBreak + // 'k1=v1' + sLineBreak + // '[S2]' + sLineBreak + // 'k2=v2' + sLineBreak + // '[S1]' + sLineBreak + // 'k3=v3' + sLineBreak + // ''; var lIni: TCustomIniFile; lSectionStrings, lValueStrings: TStrings; lKeyIdx: Integer; lSection, lKey, lValue: string; begin TFile.WriteAllText('.\test.ini', C_CONTENT); lIni := AIniFactory('.\test.ini'); try lValueStrings := TStringList.Create(); try lSectionStrings := TStringList.Create(); try lIni.ReadSections(lSectionStrings); for lSection in lSectionStrings do begin Writeln(lSection, ':'); lValueStrings.Clear(); lIni.ReadSectionValues(lSection, lValueStrings); for lKeyIdx := 0 to lValueStrings.Count - 1 do begin lKey := lValueStrings.Names[lKeyIdx]; lValue := lValueStrings.ValueFromIndex[lKeyIdx]; Writeln('- ', lKey, ' = ', lValue); end; end; finally lSectionStrings.Free(); end; finally lValueStrings.Free(); end; Writeln('<EOF>'); finally lIni.Free(); end; end; procedure Main(); begin Writeln('TMemIniFile:'); Writeln; CheckIniClass( function(AFilename: string): TCustomIniFile begin Result := TMemIniFile.Create(AFilename); end); Writeln; Writeln('TIniFile:'); Writeln; CheckIniClass( function(AFilename: string): TCustomIniFile begin Result := TIniFile.Create(AFilename); end); end; begin try Main(); except on E: Exception do Writeln(E.ClassName, ': ', E.Message); end; Readln; end.
Code:
Unter Rio
TMemIniFile:
S1: - k1 = v1 S2: - k2 = v2 S1: - k1 = v1 <EOF> TIniFile: S1: - k1 = v1 S2: - k2 = v2 S1: - k1 = v1 <EOF>
Code:
TMemIniFile:
S1: - k1 = v1 - k3 = v3 S2: - k2 = v2 <EOF> TIniFile: S1: - k1 = v1 S2: - k2 = v2 S1: - k1 = v1 <EOF> |
AW: Unterschied TMemIniFile 10.2 Tokyo / 10.3 Rio
Das steht in der Doku zu TIniFile und in ähnlicher Form auch noch für Rio, insofern erstmal dort keine Änderung. Da steht aber nirgendwo, daß TMemInifile die fehlerhafte Implementierung der WinApi nachbildet und Microsoft schweigt sich in diesem Punkt eh aus und verweist lieber auf die Registry, wo das schon gar nicht mehr gehen würde.
Insbesondere steht in der Delphi Doku nirgendwo, daß mehrere Sections mit gleichen Namen existieren dürfen. Wäre es so, müsste das Verhalten in diesem Fall irgendwo erläutert werden (z.B. was passiert bei ReadSectionValues? In welche Section wird geschrieben, wenn das Item in keiner existiert?), andernfalls wäre es undefiniert. Undefiniertes Verhalten kann sich allerdings schon mal in einer neuen Version ändern. Wie Freimatz schon sagte, gibt es keine Norm für diesen Fall, und somit kann sich Delphi auch an keine halten bzw. gehalten haben. Die Änderung des Verhaltens in Rio ist also durchaus plausibel und meiner Meinung nach auch akzeptabel, da sie eine Inkonsistenz beseitigt. Jetzt muss das nur noch irgendwer mal in die Doku aufnehmen. |
AW: Unterschied TMemIniFile 10.2 Tokyo / 10.3 Rio
Die größte Überraschung bietet sich wenn man Cross-Plattform entwickelt, denn unter Windows ist
Delphi-Quellcode:
ein Wrapper der WinAPI und bei allen anderen Plattformen ein Alias für
TIniFile
Delphi-Quellcode:
.
TMemIniFile
Und da gibt es eben ab Rio jetzt Unterschiede. |
AW: Unterschied TMemIniFile 10.2 Tokyo / 10.3 Rio
Zitat:
|
AW: Unterschied TMemIniFile 10.2 Tokyo / 10.3 Rio
Zitat:
Um das Verhalten zu konsolidieren, würde ich eher eine konsistente Implementierung von TIniFile als Spezialisierung von TMemIniFile auch unter Windows vorziehen. |
AW: Unterschied TMemIniFile 10.2 Tokyo / 10.3 Rio
Für das Verhalten von
Delphi-Quellcode:
unter Windows kann Delphi nicht wirklich etwas, das ist das Verhalten der WinAPI.
TIniFile
Aber wie Uwe schon sagte, es bleibt zu klären, wie es denn jetzt funktionieren soll. |
AW: Unterschied TMemIniFile 10.2 Tokyo / 10.3 Rio
Zitat:
Noch sinnvoller wäre aber wohl ein optionaler XML-Adapter oder so um das ganze leicht in ein moderneres Format zu bringen... |
AW: Unterschied TMemIniFile 10.2 Tokyo / 10.3 Rio
Da habe ich ja eine Diskussion losgetreten ;-)
Ich nutze meine Konstruktion mit TMemIniFile nur zum lesen der Datei, ich speichere darin nichts ab, habe ich mir jetzt einfach die "alte" Variante von TMemIniFile (< 10.3 Rio) nachgebaut und nutze diese Klasse. Damit geht alles wie vorher auch. Übrigens war das Verhalten von TMemIniFile in Tokyo auch das gleiche Verhalten wie in allen Versionen davor auch. Also nicht Tokyo hatte die "falsche" Implementierung sondern Rio ist die erste Version, die es "richtig" macht. Ob richtig oder nicht, kann sich jeder selber überlegen bzw. es nutzen wie man es eben braucht :-D |
AW: Unterschied TMemIniFile 10.2 Tokyo / 10.3 Rio
TMemIniFile basierte auf TStringList (zumindest noch vor Rio).
Hab jetzt nicht gecheckt was genau da in Rio wohl umgebaut worden ist. Zitat:
Das mehrere gleiche Sections Probleme machen können sollte auch vom Einsatz der ursprünglichen TStringList als Basis klar gewesen sein. Wenn das nun unbedingt gebraucht wird, würde ich versuchen das alte Verhalten mit TStringLists in einer eigenen Klasse oder Ableitung nachzubilden. Rollo |
AW: Unterschied TMemIniFile 10.2 Tokyo / 10.3 Rio
Hallo,
Zitat:
Aber Unit-Tests sollten sowas finden (wenn man überhaupt davon ausgeht, das das was schiefgehen kann...) |
AW: Unterschied TMemIniFile 10.2 Tokyo / 10.3 Rio
Zitat:
|
AW: Unterschied TMemIniFile 10.2 Tokyo / 10.3 Rio
Hallo,
wenn die das mit den Unit-Tests nicht machen würden, würde gar nichts nach einem Update funktionieren. Aber auch das Schreiben von guten Unit-Tests muss gelernt sein. Aber schön wäre auch mal das Compilieren der IDE mit FastMM4... ;) |
AW: Unterschied TMemIniFile 10.2 Tokyo / 10.3 Rio
Zitat:
Um nochmal auf das ursprüngliche Verhalten von TMemIniFile anhand des obigen Testprogramms zurückzukommen: Die zweite Section wird zwar bei ReadSections aufgelistet, an ihren Inhalt kommt man aber weder mit ReaadString noch ReadSectionValues ran (gleiches gilt auch für TIniFile). Wozu sollte das zweite Vorkommen dieser Section denn nun überhaupt gut sein? Eigentlich müsste man bei ReadSections diese Doublette doch besser gleich entfernen (oder eine Exception werfen). Dann hat man aber faktisch dasselbe Verhalten, als ob die doppelte Section gar nicht in der INI vorhanden wäre. In Rio wird dieses Verhalten (bewusst oder unbewusst) geändert in der Art, daß zwar die doppelte Section nicht mehr aufgeführt wird, deren Werte aber jetzt zur Verfügung stehen. Als Nebeneffekt wird beim Schreiben von TMemInifile auch noch implizit eine Normalisierung durchgeführt, bei der die doppelten Sections in einer zusammengefasst werden. Ich finde dieses Verhalten wesentlich realistischer und auch sinnvoller, wobei ich ziemlich sicher bin, daß dies nicht wirklich der Grund für diese Änderung war, sondern es sich eher um einen Nebeneffekt handelt. |
Alle Zeitangaben in WEZ +1. Es ist jetzt 09:23 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz