Autor Beitrag
AScomp
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 162


Delphi 5, Delphi 7, Delphi 2007, Delphi 2009, Delphi XE, Delphi 10 Seattle
BeitragVerfasst: 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:

ausblenden volle Höhe 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: Stringvar 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: Stringvar 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
ausblenden 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 user profile iconNarses: Delphi-Tags hinzugefügt
DeddyH
Ehemaliges Mitglied
Erhaltene Danke: 1



BeitragVerfasst: Mi 11.03.09 16:07 
Ich habe den Code nur kurz überflogen, aber möglicherweise liegt das Problem hier:
ausblenden 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 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 162


Delphi 5, Delphi 7, Delphi 2007, Delphi 2009, Delphi XE, Delphi 10 Seattle
BeitragVerfasst: 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
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 19314
Erhaltene Danke: 1747

W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: Mi 11.03.09 18:03 
user profile iconAScomp hat folgendes geschrieben Zum zitierten Posting springen:
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...
user profile iconAScomp hat folgendes geschrieben Zum zitierten Posting springen:
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 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 162


Delphi 5, Delphi 7, Delphi 2007, Delphi 2009, Delphi XE, Delphi 10 Seattle
BeitragVerfasst: 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
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 19314
Erhaltene Danke: 1747

W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: Mi 11.03.09 18:50 
user profile iconAScomp hat folgendes geschrieben Zum zitierten Posting springen:
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 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 162


Delphi 5, Delphi 7, Delphi 2007, Delphi 2009, Delphi XE, Delphi 10 Seattle
BeitragVerfasst: Mi 11.03.09 18:53 
Okay, thanks!