Entwickler-Ecke
Dateizugriff - D2009: ReadBuffer + SizeOf-Problem nach Umstieg von D2007
AScomp - Mi 11.03.09 12:27
Titel: D2009: ReadBuffer + SizeOf-Problem nach Umstieg von D2007
Hallo zusammen,
habe mal wieder ein Konvertierungsproblem. Und zwar habe ich zwei Funktionen, mit denen ich gespeicherte Daten laden bzw. Daten speichere (Dateiname und Dateidatum werden aus einem Record in eine Datei geschrieben).
Hier mal zur Veranschaulichung der Sourcecode:
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:
| type THeader = record DataCount: DWord; Reserved: DWord; end; PLogRec = ^TLogRec; TLogRec = record szPath: array[0..MAX_PATH] of Char; lTime: Longint; end; TLogData = array of TLogRec;
function LoadLogData(const AFilename: String; var LogData: TLogData): Boolean; var Header: THeader; FS: TFileStream; I: Integer; begin result := false; if not FileExists(AFilename) then exit; FS := TFileStream.Create(AFilename, fmOpenRead or fmShareDenyNone); try if FS.Size < SizeOf(THeader) then exit; FS.ReadBuffer(Header, SizeOf(THeader)); SetLength(LogData, Header.DataCount); for I := 0 to Header.DataCount - 1 do FS.ReadBuffer(LogData[I], SizeOf(TLogRec)); finally FS.Free; end; end;
function SaveLogData(const AFilename: String; var LogData: TLogData): Boolean; var Header: THeader; FS: TFileStream; I: Longint; begin result := False; if LogData = nil then exit; QuickSort(LogData); FS := TFileStream.Create(AFilename, fmCreate or fmShareDenyNone); try Header.DataCount := Length(LogData); FS.WriteBuffer(Header, SizeOf(THeader)); for I := Low(LogData) to High(LogData) do FS.WriteBuffer(LogData[I], SizeOf(TLogRec)); result := True; finally FS.Free; end; end; |
Die Logdateien alter Programmversionen, die mit Delphi 2007 programmiert worden sind, sollten natürlich genauso geladen werden können wie neu geschriebene Dateien.
Das Problem ist jetzt folgendes: In Zeile 29
Delphi-Quelltext
1:
| FS.ReadBuffer(LogData[I], SizeOf(TLogRec)); |
gibt es eine Exception (EReadError). Nicht beim ersten Durchlauf, sondern ich schätze relativ am Ende. Der Header wird noch korrekt gelesen, danach aber nichts mehr (die Dateinamen in LogData enthalten keine korrekten Daten) - ich vermute ein Problem mit der Länge (Unicode).
Viele Grüße,
Andy
Moderiert von
Narses: Delphi-Tags hinzugefügt
Delete - Mi 11.03.09 16:07
Ich habe den Code nur kurz überflogen, aber möglicherweise liegt das Problem hier:
Delphi-Quelltext
1: 2: 3: 4:
| TLogRec = record szPath: array[0..MAX_PATH] of Char; lTime: Longint; end; |
Wenn Du szPath mal als array of AnsiChar definierst, geht es dann?
AScomp - Mi 11.03.09 17:05
Hab's jetzt nicht getestet, aber selbst wenn es gehen würde: Die Logdatei könnte dann wieder keine Dateien mit Unicode-Zeichen verwalten. Dies ist aber dringend notwendig.
Hast du sonst noch eine Idee?
jaenicke - Mi 11.03.09 18:03
AScomp hat folgendes geschrieben : |
Hab's jetzt nicht getestet, aber selbst wenn es gehen würde: Die Logdatei könnte dann wieder keine Dateien mit Unicode-Zeichen verwalten. Dies ist aber dringend notwendig. |
Du widersprichst dir...
AScomp hat folgendes geschrieben : |
Die Logdateien alter Programmversionen, die mit Delphi 2007 programmiert worden sind, sollten natürlich genauso geladen werden können wie neu geschriebene Dateien. |
Die alten Dateien enthalten Buchstaben mit jeweils einem Byte pro Buchstabe (Char = 1 Byte bei Delphi <= 2007), die neuen Buchstaben mit 2 Byte (Char = 2 Byte bei Delphi 2009).
Damit hat dein TLogRec jeweils eine unterschiedliche Größe. Entweder speicherst du das mit ab oder die Kompatibilität wird nicht funktionieren. Wenn du dies mit abspeicherst, dann kannst du für das alte Format von Delphi 2007 AnsiChar und für das neue unter Delphi 2009 Char benutzen. Das neue kann dann aber von Delphi <= 2007 nicht gelesen werden, es sei denn mit Zusatzbibliotheken.
AScomp - Mi 11.03.09 18:30
Zitat: |
Du widersprichst dir... |
Nö. ;-)
Leider wird das nicht mit abgespeichert. Gibt es keine Möglichkeit zu ermitteln, ob es sich um einen Ansi- oder einen Unicode-Record handelt, der in der Datei abgelegt ist?
Oder alternativ: Wie kann man ermitteln, ob eine Datei im Ansi-Format oder im Unicode-Format gespeichert wurde?
jaenicke - Mi 11.03.09 18:50
AScomp hat folgendes geschrieben : |
Leider wird das nicht mit abgespeichert. Gibt es keine Möglichkeit zu ermitteln, ob es sich um einen Ansi- oder einen Unicode-Record handelt, der in der Datei abgelegt ist?
Oder alternativ: Wie kann man ermitteln, ob eine Datei im Ansi-Format oder im Unicode-Format gespeichert wurde? |
Gar nicht, denn du speicherst das ja selbst ab. Und deshalb gibt es auch keine Signaturen, an denen man das sonst unterscheidet.
Du kannst höchstens versuchen durch eine Division der Dateigröße minus dem Header durch die Datensatzgrößen zu schauen welche Recordgröße glatt aufgeht. Aber sauber ist das nicht und es kann zufällig auch mit beiden klappen.
Die einzige saubere Lösung wäre ein neues Dateiformat für Delphi 2009. Dieses könntest du an einer Signatur im Header identifizieren. Da das neue Format ohnehin nicht mit Delphi 2007 und früher lesbar ist, sollte das auch kein Problem sein.
AScomp - Mi 11.03.09 18:53
Okay, thanks!
Entwickler-Ecke.de based on phpBB
Copyright 2002 - 2011 by Tino Teuber, Copyright 2011 - 2025 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!