Einzelnen Beitrag anzeigen

hansklok

Registriert seit: 14. Apr 2004
Ort: Karlsruhe
318 Beiträge
 
Delphi 2010 Architect
 
#1

String aus TFileStream auslesen funktioniert nicht

  Alt 30. Dez 2010, 14:10
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

Geändert von hansklok (30. Dez 2010 um 14:23 Uhr)
  Mit Zitat antworten Zitat