Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Algorithmen, Datenstrukturen und Klassendesign (https://www.delphipraxis.net/78-algorithmen-datenstrukturen-und-klassendesign/)
-   -   FreePascal String aus TFileStream auslesen funktioniert nicht (https://www.delphipraxis.net/157116-string-aus-tfilestream-auslesen-funktioniert-nicht.html)

hansklok 30. Dez 2010 13:10


String aus TFileStream auslesen funktioniert nicht
 
Hallo,

seit 1h versuche ich krampfhaft den Fehler in einem Programmierversuch zu finden, aber ich entdecke ihn eben nicht.
Ich habe mehrere TPersons, die in einer Datei gespeichert werden. Zunächst nur das Geschlecht, Vor- & Nachname und eine Nummer. Das speichern funktioniert auch alles wunderbar, und das Laden scheinbar auch, allerdings bekomme ich keine String-Variablen (Vor- & Nachname) ausgelesen, warum??

Hier der Code:

uGenealogyProcedures.pas (Hilfs-Unit)
Delphi-Quellcode:
uses
  Classes;

  procedure StrToStream(AString: String; AStream: TFileStream);
  procedure StrFromStream(AString: String; AStream: TFileStream);

implementation

var
  Size: Integer;

procedure StrToStream(AString: String; AStream: TFileStream);
begin
  Size:= Length(AString);
  AStream.Write(Size, SizeOf(Integer));
  AStream.Write(AString[1], Size);
end;

procedure StrFromStream(AString: String; AStream: TFileStream);
begin
  AStream.Read(Size, SizeOf(Integer));
  if Size > -1 then begin
    SetLength(AString, Size);
    AStream.Read(AString[1], Size);
  end;
end;
uGenealogy.pas
Delphi-Quellcode:
uses
  Classes, Contnrs, SysUtils, uGenealogyProcedures;

type
  TSex = (sMale, sFemale, sUnknown);

  TGenealogyEntity = class(TPersistent)
    private
      fNumber: Integer;
    public
      property Number: Integer read fNumber write fNumber;

      procedure SaveToStream(AStream: TFileStream); virtual;
      procedure LoadFromStream(AStream: TFileStream); virtual;
  end;

  TPerson = class(TGenealogyEntity)
    private
      fSex: TSex;
      fFirstName,
      fLastName: String;
    public
      constructor Create(ASex: TSex; AFirstName, ALastName: String); overload;

      property Sex: TSex read fSex write fSex;
      property FirstName: String read fFirstName write fFirstName;
      property LastName: String read fLastName write fLastName;

      procedure SaveToStream(AStream: TFileStream); override;
      procedure LoadFromStream(AStream: TFileStream); override;

      function GetSex: String;
  end;

implementation

procedure TGenealogyEntity.SaveToStream(AStream: TFileStream);
begin
  AStream.Write(fNumber, SizeOf(Integer));
end;

procedure TGenealogyEntity.LoadFromStream(AStream: TFileStream);
begin
  AStream.Read(fNumber, SizeOf(Integer));
end;

constructor TPerson.Create(ASex: TSex; AFirstName, ALastName: String);
begin
  inherited Create;
  fSex:= ASex;
  fFirstName:= AFirstName;
  fLastName:= ALastName;
end;

procedure TPerson.SaveToStream(AStream: TFileStream);
begin
  AStream.Write(fSex, SizeOf(TSex));
  StrToStream(fFirstName, AStream);
  StrToStream(fLastName, AStream);
end;

procedure TPerson.LoadFromStream(AStream: TFileStream);
begin
  AStream.Read(fSex, SizeOf(TSex));
  StrFromStream(fFirstName, AStream);
  StrFromStream(fLastName, AStream);
end;

function TPerson.GetSex: String;
begin
  case fSex of
    sMale:   Result:= 'Mann';
    sFemale: Result:= 'Frau';
    sUnknown: Result:= 'Unbekannt';
  end;
end;
uGenealogyFile.pas
Delphi-Quellcode:
uses
  Classes, Contnrs, SysUtils, uGenealogy;

type
  TGenealogyFile = class(TObject)
    private
      fFileName: String;
      fPersons: TObjectList;
    public
      constructor Create;

      property FileName: String read fFileName write fFileName;

      property Persons: TObjectList read fPersons write fPersons;

      procedure SaveToFile(AFileName: String);
      procedure LoadFromFile(AFileName: String);
  end;

implementation

var
  PersonCount, i: Integer;
  GenFile: TFileStream;

constructor TGenealogyFile.Create;
begin
  inherited Create;

  fPersons:= TObjectList.Create;
  fPersons.OwnsObjects:= True;
end;

procedure TGenealogyFile.SaveToFile(AFileName: String);
begin
  fFileName:= AFileName;
  GenFile:= TFileStream.Create(AFileName, fmCreate);

  GenFile.WriteBuffer(fPersons.Count, SizeOf(Integer));
  for i:= 0 to fPersons.Count - 1 do
    TPerson(fPersons.Items[i]).SaveToStream(GenFile);

  GenFile.Free;
end;

procedure TGenealogyFile.LoadFromFile(AFileName: String);
var
  Person: TPerson;
begin
  GenFile:= TFileStream.Create(AFileName, fmOpenRead);

  GenFile.ReadBuffer(PersonCount, SizeOf(Integer));
  for i:= 0 to PersonCount - 1 do
    begin
      Person:= TPerson.Create;
      Person.LoadFromStream(GenFile);
      fPersons.Add(Person);
    end;

  GenFile.Free;
end;
Und nun noch die Main-Unit.

uMain.pas
Delphi-Quellcode:
procedure TfMain.FormCreate(Sender: TObject);
begin
  Stammbaum:= TGenealogyFile.Create;
end;

procedure TfMain.bSavePersonClick(Sender: TObject);
var
  Person: TPerson;;
begin
  Person:= TPerson.Create(TSex(rgSex.ItemIndex), leFirstName.Text, leLastName.Text);
  Stammbaum.Persons.Add(Person);
end;

procedure TfMain.FormDestroy(Sender: TObject);
begin
  Stammbaum.Free;
end;

procedure TfMain.miOpenClick(Sender: TObject);
var
  i: Integer;
begin
  if OpenDialog1.Execute then
     begin
       Stammbaum.LoadFromFile(OpenDialog1.FileName);
       Stammbaum.FileName:= OpenDialog1.FileName;
       fMain.Caption:= IntToStr(Stammbaum.Persons.Count) + ' Personen'; // funktioniert
       for i:= 0 to Stammbaum.Persons.Count-1 do
         ListBox1.Items.Add(TPerson(Stammbaum.Persons[i]).LastName + ', ' + TPerson(Stammbaum.Persons[i]).FirstName +
         ' (' + TPerson(Stammbaum.Persons[i]).GetSex + ')'); // bis auf das Geschlecht werden keine Namen angezeigt
     end;
end;

procedure TfMain.miSaveAsClick(Sender: TObject);
begin
  if SaveDialog1.Execute then
     Stammbaum.SaveToFile(SaveDialog1.FileName);
end;

procedure TfMain.miSaveClick(Sender: TObject);
begin
  if Stammbaum.FileName <> '' then
     Stammbaum.SaveToFile(Stammbaum.FileName)
  else
    miSaveAs.Click;
end;
Vielleicht kann mir bitte einer von Euch helfen. Ich bin ganz irritiert, da ich sonst immer auf diesem simplen Gerüst meine Dateiarbeiten durchführe und bis jetzt nie Probleme damit hatte.

HG hansklok

Luckie 30. Dez 2010 13:14

AW: Ich finde den Fehler nicht!
 
Bitte gebe deinem Beitrag einen aussagekräftigen Titel.

Uwe Raabe 30. Dez 2010 14:04

AW: String aus TFileStream auslesen funktioniert nicht
 
Du musst den String-Parameter in StrFromStream als
Delphi-Quellcode:
var
deklarieren.

hansklok 30. Dez 2010 14:20

AW: String aus TFileStream auslesen funktioniert nicht
 
Vielen lieben Dank. Das ist eigentlich voll peinlich, das hätte mir selbst auffallen müssen. Danke, manchmal liegt eben der Hund im Detail vergraben.

DeddyH 30. Dez 2010 15:14

AW: String aus TFileStream auslesen funktioniert nicht
 
Zitat:

Delphi-Quellcode:
function TPerson.GetSex

Sollte das nicht eher
Delphi-Quellcode:
function TPerson.GetGender
heißen? Das klingt nicht so schlüpfrig :mrgreen:

Sir Rufo 31. Dez 2010 01:59

AW: String aus TFileStream auslesen funktioniert nicht
 
Zitat:

Zitat von DeddyH (Beitrag 1071240)
Zitat:

Delphi-Quellcode:
function TPerson.GetSex

Sollte das nicht eher
Delphi-Quellcode:
function TPerson.GetGender
heißen? Das klingt nicht so schlüpfrig :mrgreen:

Mich wundert, dass das überhaupt geht.

Ich hätte gedacht daraus macht die IDE automatisch
Delphi-Quellcode:
TPerson.GetPiep
:mrgreen:


Alle Zeitangaben in WEZ +1. Es ist jetzt 19:04 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