Delphi-PRAXiS
Seite 3 von 4     123 4      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi Frage zum Buffer eines Streams (https://www.delphipraxis.net/96564-frage-zum-buffer-eines-streams.html)

sirius 29. Jul 2007 18:43

Re: Frage zum Buffer eines Streams
 
Zitat:

Zitat von alleinherrscher
Genau das hatte ich auch zuerst vor, aber macht die sache nicht wesentlich einfacher oder? *grübel* naja, ich versuche jetzt mal, in deine struktur meine Idee mit dem zusätzlichen stream einzubauen... hoffe es klappt irgendwie...

Da ist die Frage, ob deins oder meins als Grundlage jetzt besser ist :gruebel:


Edit: Wer ruft den die Read-Methode auf?
Wahrscheinlich wäre es noch sinnvoll eine savetoFile etc. Methode zu implementieren.

alleinherrscher 29. Jul 2007 18:52

Re: Frage zum Buffer eines Streams
 
@sirius:

Hm allerdings ist meins etwas unverständlich oder? Blickst du da durch?

zu deinem edit: beides wäre brauchbar: ein Read und ein SavetoFile. Aber wenn du das Read hast, ist das Savetofile doch vom selben Prinzip oder?


Und jap du hast recht, die Abstrakte Lösung ist wirklich knackig kurz und besser :)

//edit: die READ methode brauche ich später im "externen Programm"...oder wie meinst du die frage?

alzaimar 29. Jul 2007 18:54

Re: Frage zum Buffer eines Streams
 
Ich würde das in mehreren Schritten angehen:
1. Speichern der Änderungen in einer separaten Struktur:
Delphi-Quellcode:
TSavedItem = Record
  siPos,
  siSize : Cardinal;
  siData : Pointer;
End;
Wenn man einen weiteren Wert der Größe N an Stelle P speichert, und es existiert ein 'Saved Item' S an der Position P-N, dann kann man S erweitern (siPos += N). Existiert ein saved Item an der Stelle S.siPos = P+N, dann kann man S wieder erweitern (siPos -= N, siSize += N).

2. Sicherstellen, das bei einem READ auf dem Stream die unveränderten und veränderten (Saved Item Liste) korrekt zurückgeliefert werden.
3. Speichern der Saved Item Liste in einem Stream, allerdings würde ich hier die Liste im Speicher, und nur die siData-Teile auslagern. Dies dürfte sehr komplex werden, wenn es optimal performant werden soll.

Eigentlich handelt es sich um einen Stream, der mit Transaktionen arbeitet. Es gibt so eine Komponente schon, ich meine, ich hätte sie bei Torry gesehen...

alleinherrscher 29. Jul 2007 18:57

Re: Frage zum Buffer eines Streams
 
Zitat:

Zitat von alzaimar
m einen Stream, der mit Transaktionen arbeitet. Es gibt so eine Komponente schon, ich meine, ich hätte sie bei Torry gesehen...

Wenn es sowas gibt, wäre das natürlich super.

Achja und:

Zitat:

1. Speichern der Änderungen in einer separaten Struktur:
Delphi-Quellcode: markieren
TSavedItem = Record
siPos,
siSize : Cardinal;
siData : Pointer;
End;

Wenn man einen weiteren Wert der Größe N an Stelle P speichert, und es existiert ein 'Saved Item' S an der Position P-N, dann kann man S erweitern (siPos += N). Existiert ein saved Item an der Stelle S.siPos = P+N, dann kann man S wieder erweitern (siPos -= N, siSize += N).

Guck dir mal meinen Quelltext an. Genauso ists gemacht ;)

sirius 29. Jul 2007 19:42

Re: Frage zum Buffer eines Streams
 
Zitat:

Zitat von alleinherrscher
Hm allerdings ist meins etwas unverständlich oder? Blickst du da durch?

Jetzt, wo ich das Ziel sehe, schon deutlich besser :mrgreen:
Zitat:

Zitat von alleinherrscher
zu deinem edit: beides wäre brauchbar: ein Read und ein SavetoFile. Aber wenn du das Read hast, ist das Savetofile doch vom selben Prinzip oder?

Naja, wenn man von Performance spricht, hatte ich mir gedacht, dass ein savetofile aus deinem Bilderbeispiel besser ohne Read und copyFrom auskommen sollte. (Aber vielleicht geht das gar nicht)


Zitat:

Zitat von alleinherrscher
//edit: die READ methode brauche ich später im "externen Programm"...oder wie meinst du die frage?

Dein Read killt performanctechnisch doch so ziemlich alles, was du dir vorher gedacht hattest. aber wenn du sie brauchst, würde ich gerne nochmal auf deine Eingangsfrage zurückkommen. so einfach, wie meine Read-Methode geht es natürlich nicht. Aber ein extra BufferStream sollte man hier evtl. auch vermeiden.

Also, wie in einen Buffer schreiben?
Delphi-Quellcode:
procedure xyz.read(var buffer);
var buf:pointer;
begin
  buf:=@buffer;
 
  filestream.read(buf^,10);
  buf:=pointer(cardinal(buf)+10);
  filestream.seek(100,sofromcurrent);
  filestream.read(buf^,3);
  buf:=pointer(cardinal(buf)+3);
  ...
end;

alleinherrscher 30. Jul 2007 13:09

Re: Frage zum Buffer eines Streams
 
Liste der Anhänge anzeigen (Anzahl: 1)
Hey@all und Hi Sirius!

Ich hab die Änderungen mal eingebaut. Muss sagen, bis jetzt haben alle meine Tests funktioniert. Wenn du magst, kannst du (natürlich auch gerne alle anderen) mal testen, obs noch Bugs gibt. Falls dies okay ist, fehlen natürlich noch eine optimierte Version von SaveToFile.

Wie würdet ihr die angehen, ohne Read und CopyFrom zu benutzten...und ohne die Performence zu zerstören?

Grüße Alleinherrscher

//edit: noch einen Fehler entdeckt, bei CopyFrom wenn man eine Datei als Filestream eingeladen hat, verändert, dann den gesamtem Stream kopiert sind die änderungen weg...ich werd mich mal dranbegeben...

sirius 30. Jul 2007 13:42

Re: Frage zum Buffer eines Streams
 
1. Den Filestream musst du noch im Destructor freigeben
2. Die (meine) Funktion setsize funktioniert so nicht mehr. Besonders in dem Fall, wenn die Größe verkleinert wird. Denn dann kannst du ja Teile aus dem FStream löschen bzw. den Filestream kürzen.
3. Wolltest du nicht kleine Dateien statt in den FileStream erstmal in FStream laden?
4. in seek musst du evtl noch mySize anpassen (Wenn myPosition>mysize)

Zu edit (Denk daran, dass du auch bei der Anwendung von copyFrom Fehler machen kannst (ich vergesse meistens die Position zu verändern)


zu2:
Delphi-Quellcode:
procedure  TBufferstream.SetSize(Newsize:longint);
begin
  if Newsize<mysize then begin
    //Speicher freigeben (ist allerdings nicht notwendig)

   if Filestream.size<newsize then Filestream.size:=newsize; //evtl, oder du lässt die Datei bestehen
   
   //und hier jetzt für jeden Part in FStream, schauen ob er gekürzt werden kann
 
  end;
  mysize:=newsize;
end;

alleinherrscher 30. Jul 2007 13:51

Re: Frage zum Buffer eines Streams
 
Okay, das werde ich sofort ändern, danke!

//edit zu deinem Punkt drei:
Ja, aber ich glaube so ist es einfacher, weil wir nicht noch zusätzlich die Fälle unterscheiden müssen , ob der Stream jetzt "bearbeitet werden darf" oder nicht... arg: Deutsche Sprache ist zu beschränkt ;)

Noch ne grundsätzliche verständnisfrage zu den Pointern (die Deklaration vom Buffer):

Ich lese ja im Augenblick in der READ function erst den Filestream mit

Filestream.read(buf^,count);

Will ich jetzt an einer bestimmten Position ein Datenpacket aus dem MemoryStream einsetzten, wie geht das?

Ich hab es ja im Augenblick so gelöst:

Delphi-Quellcode:

  BufStart:=cardinal(buf);

if FileStream<>nil then
  begin
    FileStream.Seek(MyPosition,soFromBeginning);
    NumberOfReadByte:=Filestream.Read(buf^,count);
  end;

//und dann um das Paket irgendwie in die Mitte vom Buffer zu setzen:

buf:=pointer(BufStart+(Start-ReadStart));

//...

 FMemory.position:=MyPart.FindAtPosition-offset;
 FMemory.Read(buf^,len);
Aber scheinbar funktioniert dies nicht sauber?!

Grüße

sirius 30. Jul 2007 14:02

Re: Frage zum Buffer eines Streams
 
Oh ja, da scheint mir noch folgende Zeile zu fehlen:
Delphi-Quellcode:
if FileStream<>nil then
    begin
      FileStream.Seek(MyPosition,soFromBeginning);
      NumberOfReadByte:=Filestream.Read(buf^,count);
     
      buf:=pointer(cardinal(buf)+NumberOfReadByte); //<--- die hier
    end;
Und an der Zeile ist auch noch was komsich:
Delphi-Quellcode:
result:=NumberOfReadByte
Was ist wenn ein Block aus FMemory über die Länge von Filestream hinausgeht?
Was ist wenn von außen die erwartete Größe (=mySize) ungleich NumberOfReadByte ist? (Dann gibt übrigens copyfrom irgendsoein EReadError.)

alleinherrscher 30. Jul 2007 14:11

Re: Frage zum Buffer eines Streams
 
OMG, ja das is ja ein Dummer Fehler, ich war bis jetzt immer davon ausgegangen, dass mein Filestream länger ist, als alles andere... Aber man kann ja auch daten HINTER den Filestream schreiben...dummdummdumm... sorry! :wall:

Aber wenn ichs so mache, wie du oben getextet hast:

Delphi-Quellcode:
if FileStream<>nil then
    begin
      FileStream.Seek(MyPosition,soFromBeginning);
      NumberOfReadByte:=Filestream.Read(buf^,count);
     
      buf:=pointer(cardinal(buf)+NumberOfReadByte); //<--- die hier
    end;
Dann würden doch bei einem weiteren Read vorgang die Daten an das ENDE von Buffer weitergeschrieben, richtig? Gibt es keine Möglichkeit (so ähnlich wie beim Stream selbst), mitten in den Buffer nochmal was reinzuschreiben bzw einlesen zu lassen?

Ach, sonst muss ich es eben etwas umschreiben...ich schau mal, danke erstmal! Das is noch ne Menge Arbeit, merke ich grade...


Alle Zeitangaben in WEZ +1. Es ist jetzt 11:11 Uhr.
Seite 3 von 4     123 4      

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