Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi TWriter/TReader und Stream (https://www.delphipraxis.net/48185-twriter-treader-und-stream.html)

Taladan 21. Jun 2005 21:21


TWriter/TReader und Stream
 
Huhu.
Ich speichere mit einen TWriter meine Objectwerte ab und natülich lese ich sie per TReader. Aber wie gehe ich nu vor, wenn ich einen vorhanden stream mit den neuen Stream verbinden will? Da bereits die ganze Liste mit Writer gespeichert wird, will ich nicht jetzt auf Tstream umstellen müssen. Würde alles nur unheimlich erschweren.

Gruß dat Tala

Sprint 21. Jun 2005 23:46

Re: TWriter/TReader und Stream
 
Ich verstehe dein Problem nicht. Kannst du das mal etwas deutlicher erklären.

Taladan 25. Jun 2005 20:03

Re: TWriter/TReader und Stream
 
Ich schreibe in einen Stream alles mit TWriter und lese alles mit TReader aus. Die funktionen, z.b. von TWriter.WriteString find ich einfach praktisch (keine Längenbestimmung und so´n quatsch).
So ich kann damit vieles Schreiben, aber nicht einen bereits fertigen Stream. Mein Problem ist, das ich unbedingt den TWriter verwenden muß, weil dieser davor und danach weiter genutzt wird in einer langen uns teilweise sich selbst aufrufenden Struktur und Schleifen. Nu habe ich jetzt aber leider keine Ahnung habe, wie ich nun mit einen TWriter einen fertigen Stream schreiben kann.
Ich dachte schon an folgendes, dies ist aber nicht möglich
Delphi-Quellcode:
        dStrings := TStrings;
        dStream := TStream.Create;
        dStrings.SaveToStream(dStream);
        Writer.WriteString(dStream);

Keldorn 25. Jun 2005 20:21

Re: TWriter/TReader und Stream
 
So richtig verstehe ich dich auch nicht.
ich bin mir nicht so sicher, ob dStrings.SaveToStream(dStream); und weiteres reinschreiben mit einem Twriter-objekt funktioinert. Ich würde den Text der Stringlist ebenfalls mit dem Twriter reinschreiben.
ansosnten schreibt Twriter die Daten auch nicht sofort in den stream. Entweder du gibst das Twriter object wieder frei, oder du nutzt flushbuffer.

Mfg Frank

Taladan 25. Jun 2005 20:30

Re: TWriter/TReader und Stream
 
Das obrige war nur ein Beispiel. Bei einen TStrings gehts noch recht einfach. Aber wenn es Images oder andere selbstdefinierte Streams sind, kann ich dieses leider nicht umgehen, und leider kommt das vor. Und genau das muß ich tun, ohne den schreibprozess des TWriter zu unterbrechen...
Es muß doch eine Möglichkeit geben, mit einen TWriter Streams als rohe Datenzu schreiben. Ich weiß leider nicht wie. Wenn ich ja weiß das es rohe Daten sind, dann ist das auslesen doch auch als Rohe Daten möglich und dann per Programmcode die Umwandlung wieder in einen Stream...

Keldorn 25. Jun 2005 20:37

Re: TWriter/TReader und Stream
 
Ich würde es so machen:
- memorystream erstellen -> rohe daten reinschreiben.
- in den richtigen stream mit Twriter die größe des memorystreams reinschreiben
- den memorytream in den richtigen stream schreiben

beim auslesen andersrum, und mit hilfe der gespeicherten größe die position für das nächste Element setzen.

Mfg Frank

Taladan 25. Jun 2005 21:33

Re: TWriter/TReader und Stream
 
Das ist genau das was ich ja will, nur WIE? WIE schreibt man rohe daten mit TWriter?

Dani 25. Jun 2005 23:35

Re: TWriter/TReader und Stream
 
Hi, hatte mal dasselbe Problem. Man könnte eine Klasse von TReader/TWriter ableiten. Problem: auf das private-Element TFiler.FStream kann nur innerhalb des Moduls zugegriffen werden, in dem die Klasse deklariert ist.

Da ich nicht in Classes.pas rumpfuschen wollte musste ich eine TReader/TWriter kapselnde Klasse schreiben, die eine interne Instanz von TReader/TWriter für die "Standardoperationen" verwendet und halt zusätzlich noch eine WriteStream/LoadStream Funktion hat.

Wenn du keine Lust hast, eine extra Klasse dafür zu schreiben, kannst du natürlich auch einfach irgendwo Prozeduren deklarieren:

Delphi-Quellcode:
procedure LoadStreamFromStream(R: TReader; SourceStream, TargetStream: TStream);
var StreamSize, OldPos: Int64;
begin
  StreamSize := R.ReadInt64;
  OldPos := SourceStream.Position;
  If StreamSize > 0 then
   begin
    TargetStream.CopyFrom(SourceStream, StreamSize);
    SourceStream.Position := OldPos + StreamSize; {könnte man auch mit Seek() machen, hab aber gerade keinen Schimmer, ob CopyFrom() die Position des SourceStreams verändert}
   end;
end;

procedure SaveStreamToStream(W: TWriter; SourceStream, TargetStream: TStream);
var OldPos: Int64;
begin
  OldPos := SourceStream.Position;
  W.WriteInt64(SourceStream.Size);
  If SourceStream.Size > 0 then
   begin
    TargetStream.CopyFrom(SourceStream, SourceStream.Size);
    SourceStream.Position := OldPos;
   end;
end;
Code ohne Funktionsgarantie :mrgreen:

Eventuelles Problem: wenn man versucht einen Stream zu lesen, wo gar keiner gespeichert ist, kriegt man unvorhersehbare Daten in den TargetStream geschrieben.

Sprint 26. Jun 2005 12:04

Re: TWriter/TReader und Stream
 
Zitat:

Zitat von Taladan
Es muß doch eine Möglichkeit geben, mit einen TWriter Streams als rohe Datenzu schreiben. Ich weiß leider nicht wie. Wenn ich ja weiß das es rohe Daten sind, dann ist das auslesen doch auch als Rohe Daten möglich und dann per Programmcode die Umwandlung wieder in einen Stream...

Delphi-Quellcode:
  MemoryStream.Position := 0;
  Size := MemoryStream.Size;
  Writer.WriteInteger(Size);
  Writer.Write(MemoryStream.Memory^, Size);

Taladan 26. Jun 2005 12:37

Re: TWriter/TReader und Stream
 
Leider funktioniert es nicht. Bekomme eine unverständlichen Laufzeitfehler...

Mein Schreiben:
Delphi-Quellcode:
          Writer.WriteBoolean (true);
          MemoryStream := TMemoryStream.Create;
          MemoryStream.Position := 0;
          dstrings.SaveToStream(MemoryStream);
          MemoryStream.Position := 0;
          size := MemoryStream.Size;
          writer.WriteInteger(size);
          MemoryStream.Position := 0;
          Writer.Write(MemoryStream.Memory^, size);
Mein Lesen:
Delphi-Quellcode:
          MemoryStream := TMemoryStream.Create;
          MemoryStream.Position := 0;
          size := Reader.ReadInteger;
          MemoryStream.Position := 0;
          Reader.Read(MemoryStream.Memory^, size);
          MemoryStream.Position := 0;
          dstrings.LoadFromStream(MemoryStream);

jfheins 26. Jun 2005 12:51

Re: TWriter/TReader und Stream
 
Kannst du nicht einen TStringStream verwenden, darin speichern, und dann den String daraus mit deinem tollen TWriter-Objekt reinschreiben ?

Taladan 26. Jun 2005 13:42

Re: TWriter/TReader und Stream
 
Nein

Sprint 26. Jun 2005 14:23

Re: TWriter/TReader und Stream
 
Hier mal ein übertriebenes Beispiel:

Von einer String Variable in ein TMemoryStream und dann den TMemoryStream in TWriter schreiben:
Delphi-Quellcode:
procedure TForm1.Button1Click(Sender: TObject);
var
  Handle: Integer;
  HandleStream: THandleStream;
  MemoryStream: TMemoryStream;
  Writer: TWriter;
  S: String;
  Size: Integer;
begin

  Handle := FileCreate('M:\TEMP\TEST.TXT');
  if Handle <> -1 then
  begin
    HandleStream := THandleStream.Create(Handle);
    MemoryStream := TMemoryStream.Create;
    Writer := TWriter.Create(HandleStream, 4096);
    try
      S := 'TestString';
      MemoryStream.WriteBuffer(S[1], Length(S));
      MemoryStream.Position := 0;
      Size := MemoryStream.Size;
      Writer.WriteInteger(Size);
      Writer.Write(MemoryStream.Memory^, Size);
    finally
      Writer.Free;
      MemoryStream.Free;
      HandleStream.Free;
      FileClose(Handle);
    end;
  end;

end;
Und nun von TReader in TMemoryStream und dann in die Variable S:
Delphi-Quellcode:
procedure TForm1.Button2Click(Sender: TObject);
var
  Handle: Integer;
  HandleStream: THandleStream;
  MemoryStream: TMemoryStream;
  Reader: TReader;
  Size: Integer;
  S: String;
begin

  Handle := FileOpen('M:\TEMP\TEST.TXT', fmOpenRead);
  if Handle <> -1 then
  begin
    HandleStream := THandleStream.Create(Handle);
    MemoryStream := TMemoryStream.Create;
    Reader := TReader.Create(HandleStream, 4096);
    try
      Size := Reader.ReadInteger;
      MemoryStream.Size := Size;
      MemoryStream.Position := 0;
      Reader.Read(MemoryStream.Memory^, Size);
      MemoryStream.Position := 0;
      SetLength(S, Size);
      MemoryStream.Read(S[1], Size);
      ShowMessage(S);
    finally
      Reader.Free;
      MemoryStream.Free;
      HandleStream.Free;
      FileClose(Handle);
    end;
  end;

end;

Taladan 26. Jun 2005 14:33

Re: TWriter/TReader und Stream
 
Und wo liegt nun der unterschied zwischen deinen und meinen beispiel?

Taladan 26. Jun 2005 14:43

Re: TWriter/TReader und Stream
 
das problem schein nicht an der speicherrotine zu liegen. leider

Sprint 26. Jun 2005 14:46

Re: TWriter/TReader und Stream
 
Zitat:

Zitat von Taladan
Leider funktioniert es nicht. Bekomme eine unverständlichen Laufzeitfehler...

Zitat:

Zitat von Taladan
Und wo liegt nun der unterschied zwischen deinen und meinen beispiel?

Das ich keinen unverständlichen Laufzeitfehler bekomme.

Zitat:

Zitat von Taladan
das problem schein nicht an der speicherrotine zu liegen. leider

Dann poste mal ein komplettes Beispiel wo es nicht funktioniert.

Taladan 26. Jun 2005 14:49

Re: TWriter/TReader und Stream
 
Delphi-Quellcode:
          dStrings := TStrings.Create;

          MemoryStream := TMemoryStream.Create;
          MemoryStream.Position := 0;
          size := Reader.ReadInteger;
          memorystream.SetSize(size);
          reader.Read(MemoryStream.Memory^, Size);

          MemoryStream.Position := 0;
          dstrings.LoadFromStream(MemoryStream); //hier bekomme ich den fehler. selbst wenn ich per appent dstrings etwas zuweisen will, funktioniert es nicht, abstrakter fehler

          SetObjectProp(self, PropList^[i].Name, dstrings);
PS: Was ist ein abstrakter Fehler (für mich sind alle fehler nur ein Bahnhof)

Keldorn 26. Jun 2005 14:52

Re: TWriter/TReader und Stream
 
Delphi-Quellcode:
Var dstrings:Tstrings;
...
 dStrings := TStringlist.Create;
nie tstrings.create, dort sind viele Methoden nur als abstract definiert und sind erst in Tstringlist enthalten

Taladan 26. Jun 2005 14:55

Re: TWriter/TReader und Stream
 
Dankeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee :bounce1: :corky: :party: :spin: :hi:

Aber eine abschließende Frage: Warum ein TStrings mit einen TStringList.Create?

NicoDE 26. Jun 2005 16:17

Re: TWriter/TReader und Stream
 
Zitat:

Zitat von Taladan
Warum ein TStrings mit einen TStringList.Create?

Weil TStrings nur eine abstrakte Klasse ist und TStringList TStrings implementiert.


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