AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Programmieren allgemein Verständnisfrage Dateien in Objekten
Thema durchsuchen
Ansicht
Themen-Optionen

Verständnisfrage Dateien in Objekten

Ein Thema von FragenderHerbert · begonnen am 12. Dez 2013 · letzter Beitrag vom 13. Dez 2013
Antwort Antwort
FragenderHerbert

Registriert seit: 4. Dez 2013
47 Beiträge
 
#1

Verständnisfrage Dateien in Objekten

  Alt 12. Dez 2013, 10:08
Hallo liebe Delphianer,

ich bin so gut wi neu hier, habe Euch durch Stöbern im Internet gefunden und auch schon hier im Forum ein wenig geblättert. Leider programmiere ich noch nicht allzu lange. Ich möchte es aber gerne lernen und da habe ich schon das erste Prorblem, das ich mir nicht erklären kann.

Ich habe diese Unit geschrieben.

Delphi-Quellcode:
unit UByteStream;

interface

uses
  Sysutils, Classes;


type
  PByteStream = ^TByteStream;
  TByteStream = Class(TObject)
  private
    FFile: File Of Byte;
    FFileName: String;
  public
    constructor Create(AFileName: String; Mode: Word);
    destructor Destroy; override;
    function ReadByte: Byte;
    function Read(var Buffer: array of byte; BufSize: Longint): Longint;
    procedure WriteByte(b: Byte);
    function Write(var Buffer: array of byte; BufSize: Longint): Longint;
    function Position: Longint;
    function Size: Longint;
    procedure Seek(APos: Longint; Flag: Word);
  End;


implementation


{ TByteStream }

constructor TByteStream.Create(AFileName: String; Mode: Word);
var IResult: Integer;
begin
  inherited Create;
  System.Assign(FFile, FFileName);
  {$I-}
  if (Mode=fmOpen) or (Mode=fmOpenRead) then
  begin
    System.Reset(FFile);
    IResult := System.IOResult;
    if IResult <> 0 then fail;
  end
  else
  if Mode = fmCreate then
  begin
    System.Rewrite(FFile);
    IResult := IOResult;
    if IResult <> 0 then fail;
  end;
  {$I+}
end;

destructor TByteStream.Destroy;
begin
  System.Close(FFile);
  inherited Done;
end;

function TByteStream.ReadByte: Byte;
var b: Byte;
begin
  System.Read(FFile, b);
  Result := b;
end;

function TByteStream.Read(var Buffer: array of byte; BufSize: Longint): Longint;
var Count,Current,BufStart,BufEnd,BufPos: Word;
begin
  BufStart := Low(Buffer);
  BufEnd := High(Buffer);
  BufPos := BufStart;
  Current := System.FilePos(FFile);
  Count := Current;
  while Count < Current + BufSize do
  begin
    System.Read(FFile, Buffer[BufPos]);
    inc(BufPos);
    inc(Count);
  end;
  Result := Count - Current;
end;

procedure TByteStream.WriteByte(b: Byte);
begin
  System.Write(FFile, b);
end;

function TByteStream.Write(var Buffer: array of byte; BufSize: Longint): Longint;
var Count,Current,BufStart,BufEnd,BufPos: Word; x: array[0..1023] of byte absolute Buffer;
begin
  BufStart := Low(Buffer);
  BufEnd := High(Buffer);
  BufPos := BufStart;
  Current := System.FilePos(FFile);
  Count := Current;
  while Count < Current + BufSize do
  begin
    System.Write(FFile, Buffer[BufPos]);
    inc(BufPos);
    inc(Count);
  end;
  Result := Count - Current;
end;

function TByteStream.Position: Longint;
begin
  Result := System.FilePos(FFile);
end;

function TByteStream.Size: Longint;
begin
  Result := System.FileSize(FFile);
end;

procedure TByteStream.Seek(APos: Longint; Flag: Word);
begin
  case Flag of
    soFromBeginning: System.Seek(FFile, APos);
    soFromCurrentPos: ;
    soFromEnd: ;
  end;
end;

end.
Bei Anwendung dieser Unit erhalte ich aber einen Fehler:

"Datei nicht geöffnet". Warum ist das so?

Delphi-Quellcode:
type
  TReader = class(TObject)
   private
    MeineBytes: TByteStream;
   public
    constructor Create(Filename: String);
    destructor Destroy; override;
    procedure ReadBytes;
  end;

implementation

constructor Create(Filename: String);
begin
  inherited Create;
  MeineBytes := TByteFile.Create(FileName, fmOpen);
end;

destructor Destroy;
begin
  MeineBytes.Free;
  inherited Destroy;
end;

procedure ReadBytes;
begin
  //hier sollten die Bytes aus der Datei nun gelesen werden
  //Aber die Datei ist nicht geöffnet
end;

end.
Entweder ich bin betriebsblind und habe was entscheidendes übersehen oder eine Datei kann in einer Klasse nicht geöffnet werden.

Wenn letzteres zutrifft, warum ist das so. Ich möchte die Zusammenhänge gerne verstehen.

Wer kann mir helfen?
  Mit Zitat antworten Zitat
Benutzerbild von baumina
baumina

Registriert seit: 5. Mai 2008
Ort: Oberschwaben
1.275 Beiträge
 
Delphi 11 Alexandria
 
#2

AW: Verständnisfrage Dateien in Objekten

  Alt 12. Dez 2013, 10:12
AFileName wird übergeben aber nichts damit gemacht, stattdessen wird FFilename benutzt, das nirgends gesetzt wurde.

Delphi-Quellcode:
constructor TByteStream.Create(AFileName: String; Mode: Word);
var IResult: Integer;
begin
   inherited Create;
   System.Assign(FFile, FFileName);
Hinter dir gehts abwärts und vor dir steil bergauf ! (Wolfgang Ambros)
  Mit Zitat antworten Zitat
mkinzler
(Moderator)

Registriert seit: 9. Dez 2005
Ort: Heilbronn
39.858 Beiträge
 
Delphi 11 Alexandria
 
#3

AW: Verständnisfrage Dateien in Objekten

  Alt 12. Dez 2013, 10:22
Da ein Klassentyp eine Referenz( Zeiger-)typ ist, wird kein Zeigertyp benötigt
PByteStream = ^TByteStream;
Die Angabe der Superklasse TObject kann enfallen
TByteStream = Class(TObject) da beim Weglasen automatisch von TObject geerbt wird.

Ich würde hier aber direkt von TStream ableiten
Markus Kinzler
  Mit Zitat antworten Zitat
FragenderHerbert

Registriert seit: 4. Dez 2013
47 Beiträge
 
#4

AW: Verständnisfrage Dateien in Objekten

  Alt 13. Dez 2013, 08:42
Hallo,

danke erst mal für Eure wirklich schnellen Antworten.

@baumina:
Habe das geändert und jetzt wird die Datei geöffnet.

@mkinzler:

Ich werde in Zukunft auch von TStream ableiten. Aber vorher schau ich mir den Quelltext (Turbo Delphi) von TStream an. Da gibt es bereits jetzt jede Menge Fragen. Ich glaub, ich schau mir das in aller Ruhe erst mal an. Was ich bis jetzt gesehen habe, ist, das das Stream Objekt auch aus einer gewöhnlichen Datei liest. Bleibt die Frage, wie Objekte gelesen und geschrieben werden. Da werd ich wohl noch einige Zeit brauchen, um das zu verstehen. Will mich erst mal damit beschäftigen.
  Mit Zitat antworten Zitat
Benutzerbild von Sir Rufo
Sir Rufo

Registriert seit: 5. Jan 2005
Ort: Stadthagen
9.454 Beiträge
 
Delphi 10 Seattle Enterprise
 
#5

AW: Verständnisfrage Dateien in Objekten

  Alt 13. Dez 2013, 09:36
Mal so als Frage unter uns Kegelschwestern

Was unterscheidet deine Klasse jetzt von einem Delphi-Referenz durchsuchenTFileStream?
(Abgesehen davon, dass Delphi-Referenz durchsuchenTFileStream von Delphi-Referenz durchsuchenTStream abgeleitet ist)

Oder was erwartest du von deiner Klasse, was nicht mit Delphi-Referenz durchsuchenTFileStream erledigt werden könnte?

Oder ganz ketzerisch gefragt, was denkst du, was jemand erwartet, wenn er TByteStream liest?
Einen Stream wo Bytes drin sind? (das mit dem Dateinamen würde mich aber schon wieder überraschen - warum dann nicht TFileByteStream ?)

Ja was ist denn dann in einem Delphi-Referenz durchsuchenTStream?
(auf jeden Fall keine Hasenköttel - ich dachte immer, da sind Bytes drin)
Kaum macht man's richtig - schon funktioniert's
Zertifikat: Sir Rufo (Fingerprint: ‎ea 0a 4c 14 0d b6 3a a4 c1 c5 b9 dc 90 9d f0 e9 de 13 da 60)
  Mit Zitat antworten Zitat
Benutzerbild von p80286
p80286

Registriert seit: 28. Apr 2008
Ort: Stolberg (Rhl)
6.659 Beiträge
 
FreePascal / Lazarus
 
#6

AW: Verständnisfrage Dateien in Objekten

  Alt 13. Dez 2013, 13:37
@Sir Rufo
vielleicht wollte er einfach mal üben?
"learning by doing"

Gruß
K-H
Programme gehorchen nicht Deinen Absichten sondern Deinen Anweisungen
R.E.D retired error detector
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.063 Beiträge
 
Delphi 12 Athens
 
#7

AW: Verständnisfrage Dateien in Objekten

  Alt 13. Dez 2013, 14:21
OK, dann halt zum Üben....

Im Prinzip wurde hier einfach nur ein "File Of Byte" weggekapselt, insofern ist das schon OK.
Auch wenn da TFileStream und Co. wohl eine bessere Alternative wären.





TByteStream ist wohl kein ganz guter Name, da es ja nicht von TStreams abgeleitet ist und sonst auch kein "Stream" intern verwendet wird, bzw. es auch nur irgendwas damit zu tun hat.
Wie wäre es TBytesFile?

Wieso wird bei Write der Puffer zum Schreiben übergeben? (Var-Parameter)
An dem Buffer soll doch nichts verändert werden.

Wozu brauchst du das BufSize?
Die länge steht doch schon im Array drin. (Length)

Einem Array-Parameter kann man zwar schön statische Arrays über geben, oder ein idrekt definiertes Array (weiß jetzt nicht wie das heißt).
x.Write([1, 2, 3, 4]);

Delphi-Quellcode:
procedure Write(Buffer: array of byte); overload; // für statische Arrays und direkte Angaben
procedure Write(Buffer: TBytes); overload; // für dynamische Arrays

procedure Read(var Buffer: TBytes; Count: Longint); // nur für dynamische Arrays möglich

// oder

function Read(Count: Longint): TBytes; // ebenso
Was sind fail und done?
Wenn du kein Delphi, sondern Lazarus/FPC verwendest, dann erwähn das bitte auch.
Aber dennoch ... wieso inherited Destroy eigentlich Done und nicht das übergeordnete Destroy?

Die Variable IResult kann weg, da du den Wert eh nur einmal auswertest und das gleich in der nächsten Zeile.

Was passiert, wenn Mode "ungültig" ist, also keinem deiner behandelten Werte entspricht?

Wieso "verwirfst" du quasi das IOResult?
Das gehört an fail übergeben, oder es sollte man sonstwie auswerten und weiterreichen .... und was macht fail eigentlich?
Der Grund, also IOResult, gehört, wenn möglich übersetzt, in die Fehlermeldung mit rein, damit man weiß warum es nicht ging.
Da du die Datei komplett kapselst, gehört auch die Fehlerbehandlung koplett da rein. (ja, IOResult könnte man extern eventuell noch abfragen, aber jenachdem was fail macht, könnte das dann schon ungültig sein)

Nochmal zu den "unnötigen" Variablen, wie vorhin schon das IResult.
Delphi-Quellcode:
function TByteStream.ReadByte: Byte;
begin
  System.Read(FFile, Result);
end;
Da das Result von TByteStream.Read immer dem BufSize entspricht, ist es nutlos und es kann eine Prozedur werden.

TByteStream.Read(Buffer, BufSize) : entweder du nimmst die größe von Buffer (Length) oder den Wert von BufSize.
- bei BufSize wird der Buffer auf die "richtige" länge gebracht und nicht blind drin rumgeschrieben
- bei Length(Buffer) ist BufSize "nutzlos" und flieg raus, aus dem Code

Und wozu Read/Write das Current/FilePos brauchen, hab ich nicht verstanden, danie wirklich verwendet wird, außer es im Result wieder rauszurechnen ... hätte man bei 0 angefangen, bräuchte man es auch nicht rausrechnen, bzw. -0 ist ja nichts.

Warum macht Seek bei 2zwei Drittel des Codes Nichts? (CurrentPos und End)

Wenn du schon OpenRead und Open aka OpenReadWrite unterscheidest, dann gehort vor das Reset noch der richtige FileMode zugewiesen.



TReader ist ein blöder Name ... Was liest der denn und außerdem Delphi-Referenz durchsuchenTReader?
Wie wäre es mit TBytesReader, für das TBytesFile?

Und daß beim TReader in der Implementation der klassenname fehlt ist bestimmt nur schlimmes Copy&Paste.
Neuste Erkenntnis:
Seit Pos einen dritten Parameter hat,
wird PoSex im Delphi viel seltener praktiziert.

Geändert von himitsu (13. Dez 2013 um 14:28 Uhr)
  Mit Zitat antworten Zitat
FragenderHerbert

Registriert seit: 4. Dez 2013
47 Beiträge
 
#8

AW: Verständnisfrage Dateien in Objekten

  Alt 13. Dez 2013, 18:50
@Sir Rufo:

Ja das ist zum Üben gedacht. Ich möchte verstehen, wie ein echter Stream intern funktioniert. Den Quelltext aus der Unit Classes verstehe ich noch nicht gut genug dazu. Eigene Experimente geben mir da mehr Aufschluss.

Zitat:
OK, dann halt zum Üben....

Im Prinzip wurde hier einfach nur ein "File Of Byte" weggekapselt, insofern ist das schon OK.
Auch wenn da TFileStream und Co. wohl eine bessere Alternative wären.



TByteStream ist wohl kein ganz guter Name, da es ja nicht von TStreams abgeleitet ist und sonst auch kein "Stream" intern verwendet wird, bzw. es auch nur irgendwas damit zu tun hat.
Wie wäre es TBytesFile?

Wie gesagt, ich will die Funktionsweise des Streams verstehen lernen. Aber für meine Klasse wäre natürlich TBytesFile ein besserer Name.

Zitat:
Wieso wird bei Write der Puffer zum Schreiben übergeben? (Var-Parameter)
An dem Buffer soll doch nichts verändert werden.

Ok, das kann ich ändern. Allerdings gab es in Turbo Pascal, von wo ich das nach Delphi portiert habe, noch keine const Parameter. Heute in Delphi kann man lt Handbuch schreiben:

procedure Write(Const Buffer; Size: Longint); in Turbo Pascal noch keine const Parameter, ging es nur so:

procedure Write(var Buffer; Size: Longint);
Zitat:
Wozu brauchst du das BufSize?
Die länge steht doch schon im Array drin. (Length)
Auch wieder wahr. Für das OpenArray stimmt das. Hatte aber ursprünglich obiges Konstrukt vorgesehen. Write(var Buffer;...


Zitat von himitsu:
Einem Array-Parameter kann man zwar schön statische Arrays über geben, oder ein idrekt definiertes Array (weiß jetzt nicht wie das heißt).
x.Write([1, 2, 3, 4]);
aber? Diese Möglichkeit ist doch praktisch.

Zitat von himitsu:
markieren
Delphi-Quellcode:
procedure Write(Buffer: array of byte); overload; // für statische Arrays und direkte Angaben
Ok, Danke, hab ich verstanden. Wenn ich Array of Byte verwende gibt es ja Low() und High(), womit ich die Arraygrenzen abfragen kann. Dann muss ich halt ein Array passender Größe übergeben und das dann schreiben.

Zitat von himitsu:
procedure Write(Buffer: TBytes); overload; // für dynamische Arrays
Wo ist TBytes gleich noch mal definiert? Ist das einfach so ein Array of Byte?

Zitat von himitsu:
procedure Read(var Buffer: TBytes; Count: Longint); // nur für dynamische Arrays möglich
Das verstehe ich jetzt nicht. Oben ist gesagt, das ich Count bei einem Array of Byte weglassen kann.

Außerdem kann ich doch an ein Open Array, wie das in Turbo Pascal hieß, ein beliebig großes Array übergeben. Wenn ich dann aber aus diesem Array nicht alle Bytes lese/schreibe, wenn also Count kleiner ist als die Größe des Arrays?

(Bis gleich groß sollte ja auch noch klappen).

Zitat von himitsu:
// oder

function Read(Count: Longint): TBytes; // ebenso
Oder so. Ok!

Zitat von himitsu:
Was sind fail und done?
Statt Done muss es Destroy heißen. Die Prozedur fail gab es in Turbo Pascal zum Aufruf im Konstruktor, wenn die Instantiierung meines Objektes fehl schlägt, hier zum Beispiel, wenn meine Datei nicht geöffnet werden konnte, weil sie nicht gefunden wurde. Fail sorgt dann dafür, das der Speicher korrekt wieder frei gegeben wird.

Zitat von himitsu:
Wenn du kein Delphi, sondern Lazarus/FPC verwendest, dann erwähn das bitte auch.
Ok, werde ich zuküftig tun und ich hab ja auch schon darauf hingewiesen, das ich vorher mit Turbo Pascal programmiert habe, nun aber wirklich mit Delphi programmiere/programmieren will, nicht mit Lazarus.

Zitat von himitsu:
Aber dennoch ... wieso inherited Destroy eigentlich Done und nicht das übergeordnete Destroy?
Weil ich den Code aus Turbo Pascal übersetzt habe, das heißt, in Turbo Pascal entwickelt und dann nach Delphi portiert. In TP gab es statt der Definition

type
TMeinObjekt = Object

in Delphi

type
TMeinObjekt = class

Der Constructor hieß dort Init, der Destructor hieß Done. Ich denke, im Interesse guten Programmierstils sollte man diese Namensgebung beibehalten und erst bei den Delphi Klassen stattdessen Create und Destroy verwenden.
Aber beim Portieren habe ich wohl vergessen, das Done abzuändern. Richtig muss es heißen:

inherited Destroy.

Habe das nicht korrekt portiert.

Zitat von himitsu:
Die Variable IResult kann weg, da du den Wert eh nur einmal auswertest und das gleich in der nächsten Zeile.

Was passiert, wenn Mode "ungültig" ist, also keinem deiner behandelten Werte entspricht?
Dann darf die Datei nicht geöffnet werden und fail muss aufgerufen werden.

Delphi-Quellcode:
...
if mode=fmCreate then
begin

end else fail; //weil ha bei ungültigem Mode die Datei nicht geöffnet wird
Zitat von himitsu:
Wieso "verwirfst" du quasi das IOResult?
Das gehört an fail übergeben, oder es sollte man sonstwie auswerten und weiterreichen .... und was macht fail eigentlich?
Der Grund, also IOResult, gehört, wenn möglich übersetzt, in die Fehlermeldung mit rein, damit man weiß warum es nicht ging.
Da du die Datei komplett kapselst, gehört auch die Fehlerbehandlung koplett da rein. (ja, IOResult könnte man extern eventuell noch abfragen, aber jenachdem was fail macht, könnte das dann schon ungültig sein)
IResult habe ich eingeführt, weil ich mit Turbo Pascal meine ersten Programmierversuche gemacht habe und da habe ich gelernt, das IOResult eine Funktion ist, deren Wert direkt nach seiner Abfrage wieder auf NULL zurück gesetzt wird.

Hmmm, IOResult an fail übergeben??? Da muss ich wohl moch mal meine alten Turbo Pascal Handbücher rausholen. Ich dachte Fail sei eine Prozedur, die ich im Konstruktor aufrufen kann, wenn die Erzeugung meines Objektes fehl schlägt.

Zitat von himitsu:
Nochmal zu den "unnötigen" Variablen, wie vorhin schon das IResult.
markieren
Delphi-Quellcode:
function TByteStream.ReadByte: Byte;
begin
System.Read(FFile, Result);
end;
Da das Result von TByteStream.Read immer dem BufSize entspricht, ist es nutlos und es kann eine Prozedur werden.
Ok, Danke! Werd ich mir merken.

Zitat von himitsu:
TByteStream.Read(Buffer, BufSize) : entweder du nimmst die größe von Buffer (Length) oder den Wert von BufSize.
- bei BufSize wird der Buffer auf die "richtige" länge gebracht und nicht blind drin rumgeschrieben
- bei Length(Buffer) ist BufSize "nutzlos" und flieg raus, aus dem Code
Ok, in Delphi geht das ja. Da gibt es ja wie ich durch Handbuchgstudium soeben gelernt habe, den const Parameter. Den gibt es in Turbo Pascal noch nicht. Ursprünglich wollte ich auch statt Array of Byte eine typlose Variable nehmen.

Zitat von himitsu:
Und wozu Read/Write das Current/FilePos brauchen, hab ich nicht verstanden, danie wirklich verwendet wird, außer es im Result wieder rauszurechnen ... hätte man bei 0 angefangen, bräuchte man es auch nicht rausrechnen, bzw. -0 ist ja nichts.

Warum macht Seek bei 2zwei Drittel des Codes Nichts? (CurrentPos und End)
Will die Seek Methode so implementieren, wie die Originale und da kann ich den Parameter Origin angeben. Da kann ich ja mitgeben, ob ich ab Beginn, ab aktueller Position oder ab Ende suchen will. Diese Methode ist noch nicht fertig implementiert.

Zitat von himitsu:
Weil diese Methode noch nicht fertig implementiert ist. In Turbo Pascal nimmt die Prozedur Seek und auch die Stream Methode Seek nur die gewünschte Position entgegen, ich Delphi kann man noch angeben, ob vom Beginn des Streams, soFromBeginning, von der aktuellen Position aus, soFromCurrent oder vom Streamende aus soFromEnd gesucht werden soll. Das möchte ich implementieren.

Wenn du schon OpenRead und Open aka OpenReadWrite unterscheidest, dann gehort vor das Reset noch der richtige FileMode zugewiesen.
Hmmm, wie mache ich das?

Habe den Quellcode von Turbo Pascal aus nach Delphi übersetzt. Delphi besitze ich erst seit kurzer Zeit.

Zitat von himitsu:
TReader ist ein blöder Name ... Was liest der denn und außerdem Delphi-Referenz durchsuchenTReader?
Wie wäre es mit TBytesReader, für das TBytesFile?
TReader steht für meine TByteStream Klasse. Ist halt schlampig übernommen. Hätte besser denselben Namen TByteStream verwenden sollen.

Zitat von himitsu:
Und daß beim TReader in der Implementation der klassenname fehlt ist bestimmt nur schlimmes Copy&Paste.
Korrekt, ist nur schlimmes Copy&Paste. Hab extra noch mal meinen Quelltext daraufhin überprüft. Hab ja auch die Korrekturen und Tipps von hier eingearbeitet und die Klasse nochmals getestet.

Und wie kommen Objekte in die Datei?

TStream, der echte Stream ist doch erst mal eine Klasse, in der etwas auf die externen Datenträger geschrieben wird. Das kann erst mal so weit mit gewöhnlichen Dateifunktionen passieren. Aber wie kommt nun ein Objekt in so eine Datei? Wie gesagt, ist mir der Quelltext aus der Unit Classes da noch nicht klar zumal dort in TStream + Nachfolgern bereits Methoden aufgerufen werden, die wohl in anderen Units und anderen Klassen verborgen sind.

In der Unit Classes lese ich zum Beispiel das hier:

Delphi-Quellcode:
function TStream.ReadComponent(Instance: TComponent): TComponent;
var
  Reader: TReader;
begin
  Reader := TReader.Create(Self, 4096);
  try
    Result := Reader.ReadRootComponent(Instance);
  finally
    Reader.Free;
  end;
end;

procedure TStream.WriteComponent(Instance: TComponent);
begin
  WriteDescendent(Instance, nil);
end;
Wenn ich dann weiter schaue, finde ich zunächst das hier:

Delphi-Quellcode:
procedure TWriter.WriteDescendent(Root: TComponent; AAncestor: TComponent);
begin
  FRootAncestor := AAncestor;
  FAncestor := AAncestor;
  FRoot := Root;
  FLookupRoot := Root;
  WriteSignature;
  WriteComponent(Root);
end;
Da weiß ich aber immer noch nicht, wie WriteComponent intern arbeitet.

Aber hier wird es jetzt interessant:

Delphi-Quellcode:
procedure TWriter.WriteComponent(Component: TComponent);

  function FindAncestor(const Name: string): TComponent;
  var
    I: Integer;
  begin
    for I := 0 to FAncestorList.Count - 1 do
    begin
      Result := FAncestorList[I];
      if SameText(Result.Name, Name) then Exit;
    end;
    Result := nil;
  end;

var
  OldAncestor: TPersistent;
  OldRootAncestor: TComponent;
  AncestorComponent: TComponent;
  I: Integer;
begin
  OldAncestor := Ancestor;
  OldRootAncestor := RootAncestor;
  try
    Include(Component.FComponentState, csWriting);
    for I := 0 to Component.ComponentCount - 1 do
      if csSubComponent in Component.Components[I].ComponentStyle then
        Include(Component.Components[I].FComponentState, csWriting);
    if Assigned(FAncestorList) then
      Ancestor := FindAncestor(Component.Name);
    if Assigned(FOnFindAncestor) and ((Ancestor = nil) or
    (Ancestor is TComponent)) then
    begin
      AncestorComponent := TComponent(Ancestor);
      FOnFindAncestor(Self, Component, Component.Name, AncestorComponent,
        FRootAncestor);
      Ancestor := AncestorComponent;
    end;
    Component.WriteState(Self);
    Exclude(Component.FComponentState, csWriting);
    for I := 0 to Component.ComponentCount - 1 do
      if csSubComponent in Component.Components[I].ComponentStyle then
        Exclude(Component.Components[I].FComponentState, csWriting);
  finally
    Ancestor := OldAncestor;
    FRootAncestor := OldRootAncestor;
  end;
end;
Das möchte ich jetzt gerne verstehen.

Schreibt diese Methode die Eigenschaften und Datenfelder in den Stream? Dann müßte bei Instantiierung ein Konstruktor aufgerufen werden, nachdem die Felder der Klasse vom Reader belegt worden sind.

Das hier ist ja die Methode WriteComponent aus TWriter, offenbar wird zum Schtreiben eine Klasse verwendet, die halt das Objekt nur in den Stream schreiben kann, zum Lesen gibt es dann eine andere Klasse.

Aber bei TReader.ReadComponent() wird es richtig umfangreich. Da blick ich derzeit noch gar nicht durch. Da gibt es in der Methode jede Menge lokale Prozeduren, die verstanden sein wollen. Und dann ist da immer noch der Code der eigentlichen Methode.


.

Geändert von FragenderHerbert (13. Dez 2013 um 19:40 Uhr)
  Mit Zitat antworten Zitat
Antwort Antwort


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 17:50 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