Autor |
Beitrag |
AScomp
      
Beiträge: 162
Delphi 5, Delphi 7, Delphi 2007, Delphi 2009, Delphi XE, Delphi 10 Seattle
|
Verfasst: Mi 11.03.09 12:27
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:
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
|
|
DeddyH
Ehemaliges Mitglied
Erhaltene Danke: 1
|
Verfasst: 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 
      
Beiträge: 162
Delphi 5, Delphi 7, Delphi 2007, Delphi 2009, Delphi XE, Delphi 10 Seattle
|
Verfasst: 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
      
Beiträge: 19314
Erhaltene Danke: 1747
W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
|
Verfasst: 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 
      
Beiträge: 162
Delphi 5, Delphi 7, Delphi 2007, Delphi 2009, Delphi XE, Delphi 10 Seattle
|
Verfasst: 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
      
Beiträge: 19314
Erhaltene Danke: 1747
W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
|
Verfasst: 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 
      
Beiträge: 162
Delphi 5, Delphi 7, Delphi 2007, Delphi 2009, Delphi XE, Delphi 10 Seattle
|
Verfasst: Mi 11.03.09 18:53
|
|
|