String in typisierter Datei (typed binary) speichern

Für Fragen zur Programmiersprache auf welcher Lazarus aufbaut
Antworten
ConcAPPtLab
Beiträge: 89
Registriert: Fr 18. Apr 2014, 18:57

String in typisierter Datei (typed binary) speichern

Beitrag von ConcAPPtLab »

Hallo,

ich möchte eine Liste von Objekten in einer typisierten Datei speichern. Ein Objekt hat natürlich einen Namen (hier: fTitle/Title). Allerdings habe ich Probleme, diesen korrekt zu speichern und wieder auszulesen. Nach einer Weile und einigen unsauberen Tricks habe ich es geschafft, den String zumindest ohne Laufzeitfehler abzuspeichern. Allerdings wird beim Ausleseversuch mit einem SIGSEV-Fehler abgebrochen und beim Rantasten mit Debugger wahlweise eine Zeichenfolge mit diversen Steuerzeichen oder aber ein Hinweis á la "uncomparsed character" oder so angezeigt.

Definition der wichtigen Klassen:

Code: Alles auswählen

{ TSession }
TSession = class(TTimer)
    private
      { unwichtig (weitere Zeitstempel) }
      fMemDur: TDateTime;
      fTitle: string[50];
 
      function getTitle(): string;
 
    public
      { unwichtig (Konstruktor und weitere Prozeduren) }
      function getDuration(): TDateTime;
 
    { unwichtig (weitere Properties) }
    property memDur: TDateTime read fMemDur;
    property Title: string read getTitle;
  end;
 
{ TSessFile }
 
  TSessFile = file of TSession;
 
{ TSessionList }
 
  TSessionList = class
    private
      fSessionFile: TSessFile;
 
      fActiveSession: integer;
      fFilePath: string;
      fSessions: array of TSession;
 
      function getSession(id: integer): TSession;
      procedure setSession(id: integer; session: TSession);
 
      procedure load();
      procedure save();
 
    public
      { unwichtig (Konstruktor und weitere Prozeduren) }
 
    { unwichtig (Properties) }
  end;
 
var list: TSessionList;


Angegebene Funktionen:

Code: Alles auswählen

function TSession.getTitle(): string;
begin
  result := fTitle;
end;
 
function TSession.getDuration(): TDateTime;
begin
 
  { calculate new memory Duration }
 
    result := fMemDur + (Now() - fStartStamp);
 
end;


Laden und Speichern der Liste:

Code: Alles auswählen

procedure TSessionList.load();
var memSession: TSession;
    i: integer;
begin
 
  closeSessions();    // close all sessions
 
  assignFile(fSessionFile, fFilePath);
 
  if not DirPathExists(ExtractFilePath(fFilePath)) then
    CreateDir(ExtractFilePath(fFilePath));
 
  if fileExists(fFilePath) then
    reset(fSessionFile)
  else
    rewrite(fSessionFile);
 
  { read file content }
 
  SetLength(fSessions, fileSize(fSessionFile));
  i := 0;
 
  while not ((eof(fSessionFile)) or (i = length(fSessions)))  do
    begin
 
      Read(fSessionFile, memSession);
 
      fSessions[i] := memSession;
 
      Inc(i);
 
    end;
 
  closeFile(fSessionFile);
 
end;
 
procedure TSessionList.save();
var i: integer;
    memSession: TSession;
begin
 
  assignFile(fSessionFile, fFilePath);
  rewrite(fSessionFile);
 
  i := 0;
 
  while not (i = length(fSessions))  do
    begin
 
      memSession := fSessions[i];
 
      Write(fSessionFile, memSession);
 
      Inc(i);
 
    end;
 
  closeFile(fSessionFile);
 
end


Anzeige des Dateiinhalts:

Code: Alles auswählen

msg := '';
 
  for i:=0 to list.count-1 do
    begin
      msg := msg + 'Name: ' + list.sessions[i].Title + #13#10 +
      'Dauer: ' + FormatDateTime('hh:mm:ss', list.sessions[i].getDuration()) +
      #13#10#13#10;
    end;
 
  ShowMessage(msg);


Ich nehme an, dass das Ganze etwas damit zu tun hat, dass Strings eigentlich nicht zu den einfachen Datentypen zählen und nicht immer ohne weiteres in einer Datei gespeichert werden können. Das komische ist halt nur, dass ich so etwas in der Art nicht gerade zum ersten Mal mache.
Aber sei's drum, ich hoffe einfach Mal, dass jemand von Euch eine Lösung findet :)

LG
ConcApptLab
Definition "Strategische Fehlerkorrektur":
Solange rumprobieren bisses klappt :D

Mathias
Beiträge: 6164
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Re: String in typisierter Datei (typed binary) speichern

Beitrag von Mathias »

Code: Alles auswählen

type
TSession = class(TTimer)
    private
.....
var
  TSessFile = file of TSession;

Willst du die ganze Klasse abspeichern ?
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

braunbär
Beiträge: 369
Registriert: Do 8. Jun 2017, 18:21
OS, Lazarus, FPC: Windows 10 64bit, Lazarus 2.0.10, FPC 3.2.0
CPU-Target: 64Bit
Wohnort: Wien

Re: String in typisierter Datei (typed binary) speichern

Beitrag von braunbär »

Ich wäre nie auf die Idee gekommen, ein File of class zu erstellen, und ich glaube auch nicht, dass das eine gute Idee ist.
Aber ein

Code: Alles auswählen

Read(fSessionFile, memSession);
ohne vorher Speicher für memsession anzulegen

Code: Alles auswählen

memsession:=Tsession.create
kann nur schiefgehen.

ConcAPPtLab
Beiträge: 89
Registriert: Fr 18. Apr 2014, 18:57

Re: String in typisierter Datei (typed binary) speichern

Beitrag von ConcAPPtLab »

Ohh Mann, vielen Dank euch beiden. Meine Lazarus-Kenntnisse sind echt eingerostet!
Werde jetzt erst einmal ein Record mit den zu speichernden Daten definieren und diese dann in der Datei speichern.

Schäme mich gerade so sehr ... XD
Definition "Strategische Fehlerkorrektur":
Solange rumprobieren bisses klappt :D

Antworten