AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

Frage zum Buffer eines Streams

Ein Thema von alleinherrscher · begonnen am 26. Jul 2007 · letzter Beitrag vom 2. Aug 2007
Antwort Antwort
Seite 2 von 4     12 34      
Benutzerbild von alleinherrscher
alleinherrscher

Registriert seit: 8. Jul 2004
Ort: Aachen
797 Beiträge
 
Delphi XE2 Professional
 
#11

Re: Frage zum Buffer eines Streams

  Alt 29. Jul 2007, 12:47
Mit MemoryMappedFiles kenne ich mich gar nicht aus. Aber ich hab mal ein bisschen gesucht. Irgendjemand meinte hier im Forum mal, dass die eigentlich für andere zwecke eingesetzt werden sollen.

Unterdessen habe ich mal ein bisschen weiterprogrammiert. Das schreiben in meinen BufferedStream und das Lesen funktionieren jetzt eigentlich ganz gut. Ich füge keine Buffer zusammen (wonach ich ursprünglich oben gefragt hatte, sondern ich nehme noch einen zusätzlichen Hilfstream, in den ich alle Speicherteile einfüge und den ich dann am schluss einmal komplett auslese -> dieser Buffer wird dann als result übergeben. (hm schwer zu beschreiben)

Allerdings bekomme ich richtig probleme, wenn ich versuch über die Stream.CopyFrom Funktion Daten aus meinem BufferedStream in einen anderen, z.B: MemoryStream zu kopieren. Dann kommt eine Böse Speicherzugriffsverletzung.

Weiß jemand, welche Prozeduren von TStream aufgerufen werden, wenn man die TStream.CopyFrom(BufferedStream,0) Prozedur aufruft?

Desweiteren habe ich etwas eigenartiges in der Delphi Hilfe gelesen:

Zitat:
TStream ist eine abstrakte bzw, rein virtuelle (C++ Terminologie) Klasse. Erstellen Sie keine Instanzen von TStream. Dieser Typ enthält abstrakte bzw. virtuelle Methoden, die überschrieben werden müssen. Abgeleitete Stream-Objekte wie Speicher- und Datei-Streams, die für Stream-Operationen mit Komponenten eingesetzt werden, werden beim Einsatz der globalen Funktionen ReadComponentRes und WriteComponentRes automatisch erstellt. Wenn andere Arten von Informationen in den Stream gestellt werden sollen, wählen Sie eine abgeleitete Klasse, die den jeweiligen Daten- und Speicherbedarf erfüllt.
Warum soll ich keine Instanzen von TStream erzeugen? Heißt das, dass das was ich vorhab eh nicht funktionieren wird?

Grüße, und vielen Dank für eure Antworten,

Alleinherrscher
„Software wird schneller langsamer als Hardware schneller wird. “ (Niklaus Wirth, 1995)

Mein Netzwerktool: Lan.FS
  Mit Zitat antworten Zitat
Benutzerbild von sirius
sirius

Registriert seit: 3. Jan 2007
Ort: Dresden
3.443 Beiträge
 
Delphi 7 Enterprise
 
#12

Re: Frage zum Buffer eines Streams

  Alt 29. Jul 2007, 13:36
1. TStream ist insofern eine abstrakte Klasse, als dass die wichtigsten Methoden (auf die auch alle anderen mit zugreifen) abstrakt deklariert sind. Ausserdem legt TStream sich noch nicht auf einen Speicherplatz fest (hat also keine Variable o.ä. wo es irgendetwas speichern könnte). Das bedeutet, erst wenn man dem TStream sagt, dass es als Memorystream arbeiten soll, gibt es da eine Pointervariable, die auf den Speicherplatz zeigt und ausgefüllte read und write Methoden, die dort Speichern können. Ähnliches gilt für TFilestream. Also, erst wenn TStream zum Filestream wird, erhält die Sache zum speichern eine Datei und die entsprechenden read und write Methoden.
Dagegen sind andere Methoden, wie Readbuffer und Writebuffer, ReadComponent, etc. pp. schon in TStream vollständig implementiert. Sie benutzen eben immer read und write und ihnen ist dann völlig egal, ob dahinter ein FileHandle oder ein "Memory"-Pointer, oder ein String (TStringStream) liegt.
Neben read und write ist noch SetSize und Seek abstrakt.
Wenn du von TStream ableitest, musst du alle abstrakten Methoden überschreiben (override) und kannst dir eben bei Read und Write deinen eigenen Speichertyp aussuchen. Das ist ja so in etwas das, was du auch willst.

Du hast es nur verkehrtherum gemacht. Du musst nicht readbuffer und writebuffer überschreiben, sondern nur read und write.

2. CopyFrom ruft readbuffer und writebuffer auf. Du kannst doch auch im Source nachschauen.

Edit: Du kannst doch nicht im Source nachschauen. Hol dir doch mal Turbo Delphi...
Edit2: Achtung beim überschreiben von setsize und seek. Die Methoden sind überladen.
Dieser Beitrag ist für Jugendliche unter 18 Jahren nicht geeignet.
  Mit Zitat antworten Zitat
Benutzerbild von alleinherrscher
alleinherrscher

Registriert seit: 8. Jul 2004
Ort: Aachen
797 Beiträge
 
Delphi XE2 Professional
 
#13

Re: Frage zum Buffer eines Streams

  Alt 29. Jul 2007, 14:02
Danke, sirius, ich hoffe jetzt komme ich erstmal weiter... ich werd mal versuchen deine tipps umzusetzten und mich dann nochmal melden!
Muss ich also alle überladenen Methoden überschreiben? wie sieht da die deklaration aus?
„Software wird schneller langsamer als Hardware schneller wird. “ (Niklaus Wirth, 1995)

Mein Netzwerktool: Lan.FS
  Mit Zitat antworten Zitat
Benutzerbild von 3_of_8
3_of_8

Registriert seit: 22. Mär 2005
Ort: Dingolfing
4.129 Beiträge
 
Turbo Delphi für Win32
 
#14

Re: Frage zum Buffer eines Streams

  Alt 29. Jul 2007, 14:13
procedure/function <Name und Parameter>; override;
Manuel Eberl
„The trouble with having an open mind, of course, is that people will insist on coming along and trying to put things in it.“
- Terry Pratchett
  Mit Zitat antworten Zitat
Benutzerbild von sirius
sirius

Registriert seit: 3. Jan 2007
Ort: Dresden
3.443 Beiträge
 
Delphi 7 Enterprise
 
#15

Re: Frage zum Buffer eines Streams

  Alt 29. Jul 2007, 14:46
Ich habe nochmal (genauer) nachgeschaut.
Nee, nicht alle überladenen Methoden. Die int64 Varianten prüfen !derzeit! nur ob der Bereich innerhalb von longint ist und rufen dann die LongInt varianten auf (ansonsten gibts ne Exception). ==> Es reichen die LongInt Varianten.

Übrigens: SetSize und Seek sind zwar nicht abstrakt, sie haben nur keinen wirklichen Inhalt. Also SetSize(Longint) ist tatsächlich leer und seek überprüft nur ob es eine neue Implementation von Seek gibt. Wenn nicht wird ne Exceptuion geworfen...hätte man es da nicht gleich abstrakt machen können

(Alle Auskünfte ... so weit ich den Code verstanden habe)
Dieser Beitrag ist für Jugendliche unter 18 Jahren nicht geeignet.
  Mit Zitat antworten Zitat
Benutzerbild von alleinherrscher
alleinherrscher

Registriert seit: 8. Jul 2004
Ort: Aachen
797 Beiträge
 
Delphi XE2 Professional
 
#16

Re: Frage zum Buffer eines Streams

  Alt 29. Jul 2007, 15:07
Hm, ich hab es jetzt mal so umprogrammiert (ich hänge die entsprechende Unit mal an, ich glaub das ist besser als die hier einzukopieren.

Allerdings bleibt die Zugriffsverletzung (wenn ich z.B TMemoryStream.CopyFrom(TBufferedStream,0) ) teste.

Kannst du evtl. mal meine Deklarationen checken, sirius? Ich hab leider nicht so viel Ahnung von Klassenableitungen und überladen von Funktionen?

Bekommst auch ein Eis von mir ausgegeben, wenn das wetter besser ist und du mal in meiner Nähe bist

Tausend Dank!!!!!!!!!!!!!!!!

//edit: Jetzt sagt nicht, ich muss die Read Function auch überladen?!?!?! In der Borland Hilfe stehen ungefähr 15 überladene Funkionen davon...
Angehängte Dateien
Dateityp: pas bufferedstream_200.pas (7,2 KB, 7x aufgerufen)
„Software wird schneller langsamer als Hardware schneller wird. “ (Niklaus Wirth, 1995)

Mein Netzwerktool: Lan.FS
  Mit Zitat antworten Zitat
Benutzerbild von sirius
sirius

Registriert seit: 3. Jan 2007
Ort: Dresden
3.443 Beiträge
 
Delphi 7 Enterprise
 
#17

Re: Frage zum Buffer eines Streams

  Alt 29. Jul 2007, 17:30
Hmm..ich weis nicht, was du mit den ganzen parts so machst.
Bevor ich da durchsehe und das auseinanderbaue, habe ich mal versucht, deine Absicht in einer anderen Klasse niederzuschreiben.
(Allein, der Sinn fehlt mir noch, aber egal)

Delphi-Quellcode:
unit Unit2;

interface

uses classes;

type tBufferStream=class(TStream)
         constructor create(const OpenFromFileName:string;TempDirectory:string); reintroduce;
         destructor Destroy; override;
       private
         FMemory:TStream;
         TempDir,TempFile:string;
         swapsize:integer;
       protected
         procedure SetSize(NewSize: Longint); override;
       public
         function Read(var Buffer; Count: Longint): Longint; override;
         function Write(const Buffer; Count: Longint): Longint; override;
         function Seek(Offset: Longint; Origin: Word): Longint; override;
end;



implementation

uses sysutils;

function GetTempFileName(TempDirectory:String):string;
var filename:string;
    i:integer;
begin
i:=0;
filename:=inttostr(i)+'.part';
while fileexists(TempDirectory+filename) do
begin
  inc(i);
  filename:=inttostr(i)+'.part';
end;
result:=TempDirectory+filename;
end;


constructor TBufferStream.create(const OpenFromFileName:string;TempDirectory:string);
var f:Tfilestream;
begin

  TempDir:=TempDirectory;

  swapsize:=5*1024;

  if openfromfilename<>'then
  begin
    f:=Tfilestream.Create(OpenFromFileName,fmopenread);
    if f.size>swapsize then FMemory:=TFilestream.Create(gettempfilename(tempdir),fmcreate)
                       else Fmemory:=TMemoryStream.Create;
    Fmemory.CopyFrom(f,f.size);
    f.free;
  end else Fmemory:=nil;



end;

function Tbufferstream.Write(const Buffer;Count: Longint): Longint;
var tmp:TStream;
begin
  if Fmemory=nil then Fmemory:=Tmemorystream.Create;
  if (Fmemory is TMemoryStream) and
     (Fmemory.Size+count>swapsize) then
  begin
    tempfile:=gettempfilename(tempdir);
    tmp:=TfileStream.Create(tempfile,fmcreate);
    Fmemory.Seek(0,sofrombeginning);
    tmp.CopyFrom(Fmemory,fmemory.size);
    Fmemory.Free;
    FMemory:=tmp;
  end;
  result:=Fmemory.Write(buffer,count)
end;
function TBufferStream.read(var Buffer;Count: Longint): Longint;
begin
  result:=FMemory.Read(buffer,count);
end;
function TbufferStream.Seek(Offset: Longint; Origin: Word): Longint;
begin
  result:=Fmemory.Seek(offset,origin);
end;

procedure Tbufferstream.SetSize(Newsize:longint);
var tmp:TStream;
begin
  if FMemory=nil then Fmemory:=Tmemorystream.Create;

  Fmemory.Size:=newsize;
  if (newsize<swapsize*2/3) and
      (Fmemory is TFilestream) then
  begin
    tmp:=Tmemorystream.Create;
    Fmemory.Seek(0,sofrombeginning);
    tmp.CopyFrom(FMemory,newsize);
    fmemory.Free;
    fmemory:=tmp;
    deletefile(tempfile);
  end;

  if (newsize>swapsize) and
      (Fmemory is TMemorystream) then
  begin
    tempfile:=gettempfilename(tempdir);
    tmp:=TFilestream.Create(tempfile,fmcreate);
    Fmemory.Seek(0,sofrombeginning);
    tmp.CopyFrom(FMemory,newsize);
    fmemory.Free;
    fmemory:=tmp;
  end;

end;

destructor TbufferStream.Destroy;
begin
  if Fmemory<>nil then
  begin
    if FMemory is TFileStream then
    begin
      Fmemory.Free;
      deletefile(TempFile);
    end
    else Fmemory.Free;
  end;
end;

end.
Jetzt ist mir auch übrigens klar, was deine Eingangsfrage war. Wenn der Buffer untypisiert ist, dann musst du eben auch ganz untypisiert rangehen:
Delphi-Quellcode:
var buffer:pointer;
begin
  GetMem(Buffer,10);
  Stream.ReadBuffer(Buffer^,10);
  //...

  FreeMem(Buffer,10);
end;
Dieser Beitrag ist für Jugendliche unter 18 Jahren nicht geeignet.
  Mit Zitat antworten Zitat
Benutzerbild von alleinherrscher
alleinherrscher

Registriert seit: 8. Jul 2004
Ort: Aachen
797 Beiträge
 
Delphi XE2 Professional
 
#18

Re: Frage zum Buffer eines Streams

  Alt 29. Jul 2007, 18:55
DANKE!!!

Ich werds direkt probieren!!!!! Mensch, wenn das klappt, das wäre richtig toll...

Wenn du magst schreib ich dir nochmal was zu dem "Sinn und Zweck", jedenfalls so wie ich mir das gedacht habe. Aber ich versuche erstmal weiterzukommen

Lg, Alleinherrscher

//edit: Du kopierst am Anfang die Daten einmal in einen neuen Stream! Im grunde eine gute Idee, aber was passiert, wenn die Datei, die in den Stream soll, richtig groß, z.B. 1GB ist? dann muss er doch den gesamten 1GB File praktisch komplett kopieren oder? Genau das gilt es ja zu verhindern um schneller arbeiten zu können...aber ich werde es einfach mal testen, vielleicht ists so ja auch schnell!

edit2: ich habe mal schnell eine kleine Grafik gemacht, was ich überhaupt genau will...

http://lanfs.la.funpic.de/Privat/Unbenannt.jpg



Vielen vielen Dank für die ganze Mühe!!!
„Software wird schneller langsamer als Hardware schneller wird. “ (Niklaus Wirth, 1995)

Mein Netzwerktool: Lan.FS
  Mit Zitat antworten Zitat
Benutzerbild von sirius
sirius

Registriert seit: 3. Jan 2007
Ort: Dresden
3.443 Beiträge
 
Delphi 7 Enterprise
 
#19

Re: Frage zum Buffer eines Streams

  Alt 29. Jul 2007, 19:29
Ahhh, ok.
Sehr interessante Komponente. die Aufgabe erfüllt meine allerdings nicht. Ich hatte dem aFileStream nicht so ein große Beachtung geschenkt, wie es notwendig wäre.

Was wäre, wenn du in den MemoryStream auch gleich die Positionen mit speichern würdest?

Edit: Es haben sich grad so ziemlich alle Fragen meinerseits bezüglich deines Codes geklärt.
Aber einiges musst du noch ändern. CopyFrom liefert z.B. Fehler, wenn du über das Ende des Streams hinausliest:
Delphi-Quellcode:
aFileStream.Position:=Pos;
BufferStream.copyfrom(aFilestream,count);
Hier ist (so weit ich sehe) nicht sichergestellt, dass Pos+Count < aFileStream.size.

Und bei mir siehst du wofür abstrakte Methoden nützlich sind. Ich brauche nicht ein Memorystream und einen Filestream extra. ich habe einfach nur einen Stream und trotzdem kann ich die Methoden read und write benutzen, da ich den Stream mit TMemorystream oder eben TFilestream erzeuge. Und ich bruache auch keine Variable swapped, da ich meine Stream-Variable abfragen kann, was sie gerade ist.
Dieser Beitrag ist für Jugendliche unter 18 Jahren nicht geeignet.
  Mit Zitat antworten Zitat
Benutzerbild von alleinherrscher
alleinherrscher

Registriert seit: 8. Jul 2004
Ort: Aachen
797 Beiträge
 
Delphi XE2 Professional
 
#20

Re: Frage zum Buffer eines Streams

  Alt 29. Jul 2007, 19:34
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...
„Software wird schneller langsamer als Hardware schneller wird. “ (Niklaus Wirth, 1995)

Mein Netzwerktool: Lan.FS
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 2 von 4     12 34      


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:29 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