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 1 von 4  1 23     Letzte »    
Benutzerbild von alleinherrscher
alleinherrscher

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

Frage zum Buffer eines Streams

  Alt 26. Jul 2007, 22:53
Hi!

Ganz simple Frage diesesmal:

Der Read und Write Procedure eines Streams kann man einen Buffer (Void Typ) übergeben, der die Daten enthält, die zu lesen und schreiben sind.

Was ist dieser Buffer intern? Ein Array of Byte?
Kann ich einen Buffer vordefinierter Länge manuell erzeugen und dann an verschiedenen Stellen des Buffers selber Daten reinschreiben? Also wenn ich z.B. 3 "Buffer" haben...kann ich die irgendwie zu einem Buffer vereinigen?


Danke und viele Grüße
Euer 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
 
#2

Re: Frage zum Buffer eines Streams

  Alt 26. Jul 2007, 23:01
Der Buffer ist einfach ein Stück Spiecher, der dir gehört; den du also reserviert hast. Das kann ein array sein, ein string oder einfach nur ein pointer auf ein stück freien Speicher.

Was willst du denn genau machen?
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
 
#3

Re: Frage zum Buffer eines Streams

  Alt 26. Jul 2007, 23:13
Stell dir vor, ich hätte z.B. 3 verschiedene MemoryStreams,
meine Prozedur soll jedem Stream ein Stückchen "Buffer" lesen können, und am Schluss die drei aus dem Speicher eingelesenen Teile zusammenfügen.

Ich könnte zwar erst aus den drei Streams die jeweiligen Stückchen per Copystream in einen neuen Stream kopieren und dann diesen komplett lesen, aber das erscheint mir etwas doppelt gemoppelt und Speicherauswendig, wenn die Streams groß sind.

Grüße
„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
 
#4

Re: Frage zum Buffer eines Streams

  Alt 26. Jul 2007, 23:18
Und was ist deine Zielvariable?

Also für string dürfte es so aussehen:
Delphi-Quellcode:
setlength(s,30);
stream1.read(s[1],10);
stream2.read(s[11],10);
stream3.read(s[21],10);
Ähnlich sieht es für arrays aus.
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
 
#5

Re: Frage zum Buffer eines Streams

  Alt 26. Jul 2007, 23:26
Meine Zielvariablen sind unterschiedlich. Einmal nen String, dann wieder n Integer, dann Daten die nen ganzes Bild enthalten und so... kann man das irgendwie "allgemein" machen?
„Software wird schneller langsamer als Hardware schneller wird. “ (Niklaus Wirth, 1995)

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

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

Re: Frage zum Buffer eines Streams

  Alt 28. Jul 2007, 16:45
*push*
„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
 
#7

Re: Frage zum Buffer eines Streams

  Alt 28. Jul 2007, 17:00
Du musst nicht nur pushen, sondern deine Frage mal genauer stellen, wenn bisher keiner geantwortet hat
Ich weis nämlich nicht, was du noch willst.
Dieser Beitrag ist für Jugendliche unter 18 Jahren nicht geeignet.
  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
 
#8

Re: Frage zum Buffer eines Streams

  Alt 28. Jul 2007, 18:13
Prinzipiell ist ein Buffer ein Stück Speicher, von dem du die Anfangsposition und die Länge weißt. Ein Buffer kann ein Integer sein, ein String, ein Record, ein statisches oder dynamisches Array - kurz, alles, was Speicher braucht.

Wenn du mehrere Variablen hast, geht das so:

Delphi-Quellcode:
var a, b: Integer;
    c: String;
    d: TMyRecord;
    e: Single;
    f: array of Integer;
    g: array[0..2] of Single;
    s: TStream;
begin
  //...
  s.Write(a, 4); //oder s.Write(a, sizeof(a)); oder s.Write(a, sizeof(Integer));
  s.Write(b, 4);
  s.Write(c, length(c)); //Aufpassen bei Multibyte-Char-Strings
  s.Write(d, sizeof(d));
  s.Write(e, 4); //oder s.Write(e, sizeof(e)); usw.
  s.Write(f[0], length(f)*4); //oder s.Write(f[0], length(f)*sizeof(Integer));
  s.Write(g[0], length(g)*4); //oder s.Write(g, length(g)*4); oder s.Write(g, length(g)*sizeof(Single));
  //...
end;
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 alleinherrscher
alleinherrscher

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

Re: Frage zum Buffer eines Streams

  Alt 28. Jul 2007, 20:35
Ich kann euch ja mal meinen Quelltext so far zuschicken. Es geht um einen etwas erweiteren Stream. Man soll ihn aus Dateien einlesen können und dann in den Stream schreiben können, ohne dabei die Datei selbst zu ändern oder die gesamte Datei in den Arbeitsspeicher zu laden.

Ich hatte schonmal früher einen Thread dazu gestartet: hier

Delphi-Quellcode:
unit BufferedStream;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs;


  type
   aPart = ^TPart;
   TPart = record
      PositionInStream:integer;
      Length:integer;
      FindAtPosition:integer;
   end;

   aBuffer=record
    MemoryStream:TMemoryStream;
    FileStream:TFilestream;
    Swaped:Boolean;
    PartsInfo:array of aPart;
   end;

   TBufferedStream = class(TStream)
     Constructor Create(OpenFromFilename:string;TempDirectory:string);
     function write(Const Buffer;Count:integer):integer;
     procedure ManageStreamType;
     procedure ReadBuffer(var Buffer;Count:integer);
     procedure WriteBuffer(Const Buffer;Count:integer);
     function read(var Buffer;Count:integer):integer;
  private
    { Private-Deklarationen }
    aFileStream:TFilestream;
    Buffer:aBuffer;
    swapsize:integer;
    TempFileName:string;
    TempDirectory:string;
    procedure SetPos(newpos:int64);
    procedure setsize(newsize:int64);
  public
    gSize:int64;
    Pos:int64;
    property Position: int64 read Pos write SetPos;
    property Size: int64 read gSize write Setsize;
    { Public-Deklarationen }
  end;

implementation

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;

procedure TBufferedStream.setsize(newsize:int64);
begin
  gSize:=newsize;
end;

procedure TBufferedStream.SetPos(newpos:int64);
begin
  pos:=newpos;
end;

procedure TBufferedStream.ManageStreamType;
begin
  with Buffer do
  begin
    if Swaped then
      begin
        if FileStream.size<(2/3)*Swapsize then
          begin
            MemoryStream:=TMemoryStream.Create;
            FileStream.Position:=0;
            MemoryStream.CopyFrom(FileStream,FileStream.size);
            freeandnil(Filestream);
            DeleteFile(TempFileName);
            Swaped:=False;
          end
      end
    else
      if MemoryStream.size>Swapsize then
         begin
           Filestream.Create(TempFileName,fmCreate);
           MemoryStream.Position:=0;
           FileStream.CopyFrom(MemoryStream,MemoryStream.size);
           freeandnil(MemoryStream);
           Swaped:=True;
         end;
  end;
end;

procedure TBufferedStream.WriteBuffer(Const Buffer;Count:integer);
var addsize:integer;
begin

with self.Buffer do
begin
  SetLength(PartsInfo,Length(PartsInfo)+1);
  PartsInfo[Length(PartsInfo)-1]:=new(aPart);
  PartsInfo[Length(PartsInfo)-1].PositionInStream:=Pos;
  PartsInfo[Length(PartsInfo)-1].Length:=Count;

if Swaped then
  begin
    FileStream.Position:=FileStream.size;
    PartsInfo[Length(PartsInfo)-1].FindAtPosition:=Filestream.Position;
    FileStream.Write(Buffer,count);
  end
else
  begin
    if MemoryStream.Size+Count>SwapSize then
      begin
           Filestream:=TFilestream.Create(TempFileName,fmCreate);
           MemoryStream.Position:=0;
           FileStream.CopyFrom(MemoryStream,MemoryStream.size);
           freeandnil(MemoryStream);
           Swaped:=True;
           FileStream.Position:=FileStream.size;
           PartsInfo[Length(PartsInfo)-1].FindAtPosition:=Filestream.Position;
           FileStream.Write(Buffer,count);
      end
    else
      begin
        MemoryStream.Position:=MemoryStream.Size;
        PartsInfo[Length(PartsInfo)-1].FindAtPosition:=MemoryStream.Position;
        MemoryStream.Write(Buffer,Count);
      end;
  end;

end;

addsize:=Count-(gSize-Pos);
Pos:=Pos+Count;

if addsize>0 then
  gSize:=gSize+addsize;

end;




procedure TBufferedStream.ReadBuffer(var Buffer;Count:integer);
var i:integer;
    len:integer;
    Start:integer;
    Ende:integer;
    PartStart:integer;
    PartEnde:Integer;
    InvolvedParts:TList;
    MyPart:aPart;
    BufferStream:Tmemorystream;
    offset:integer;
    ReadStart,ReadEnd:integer;
begin

//Zunächst alle Parts finden, die ganz oder Teilweise im zu lesenden Streamabschnitt stecken:

InvolvedParts:=TList.Create;

with self.Buffer do
for i:=0 to length(PartsInfo)-1 do
begin
  Start:=Pos;
  Ende:=Pos+Count;
  PartStart:=PartsInfo[i].PositionInStream;
  PartEnde:=PartsInfo[i].PositionInStream+PartsInfo[i].length;
  if ((PartStart>=Start) and (PartStart<Ende))
    or ((PartEnde>=Start) and (PartEnde<Ende))
    or ((PartStart<=Start) and (PartEnde>=Ende))
  then
     InvolvedParts.Add(PartsInfo[i]);

end;


//Jetzt den Stream zusammensetzten

BufferStream:=TMemorystream.create;

BufferStream.SetSize(count);

if self.aFileStream<>nil then
  begin
    aFileStream.Position:=Pos;
    BufferStream.copyfrom(aFilestream,count);
  end;


while InvolvedParts.count>0 do
begin

  MyPart:=InvolvedParts.First;
  PartStart:=MyPart.PositionInStream;
  PartEnde:=PartStart+MyPart.Length;

  If Start<PartStart then ReadStart:=PartStart
                        else ReadStart:=Start;

  If Ende<PartEnde then ReadEnd:=Ende
                        else ReadEnd:=PartEnde;

 len:= ReadEnd-ReadStart;


 Bufferstream.position:= Start-ReadStart;


 offset:=PartStart-ReadStart;

 if offset>0 then offset:=0;

 if self.Buffer.swaped then
   begin
    self.Buffer.FileStream.position:=MyPart.FindAtPosition-offset;
    BufferStream.CopyFrom(Self.Buffer.FileStream,len);
   end
 else
   begin
    self.Buffer.MemoryStream.position:=MyPart.FindAtPosition-offset;
    BufferStream.CopyFrom(Self.Buffer.MemoryStream,len);
   end;


 InvolvedParts.Delete(InvolvedParts.IndexOf(MyPart));

end;

Pos:=Pos+count;

BufferStream.Position:=0;
BufferStream.Read(Buffer,count);

freeandnil(BufferStream);


end;














function TBufferedStream.read(var Buffer;Count:integer):integer;
begin

readbuffer(Buffer,count);

end;




function TBufferedStream.write(Const Buffer;Count:integer):integer;
begin


  WriteBuffer(Buffer,Count);

end;





Constructor TBufferedStream.Create(OpenFromFilename:string;TempDirectory:string);
var i: integer;
begin

Self.TempDirectory:=TempDirectory;

SwapSize:=5*1024;

Pos:=0;
gSize:=0;

TempFileName:=GetTempFileName(TempDirectory);

aFileStream:=Nil;

if OpenFromFileName<>'then
begin
  aFileStream:=TFilestream.Create(OpenFromFileName,fmOpenRead);
  gSize:=aFilestream.Size;
  aFilestream.Position:=0;
end;

with Buffer do
begin
  MemoryStream:=TMemoryStream.Create;
  Swaped:=False;
  SetLength(PartsInfo,0);
end;





end;

end.
Angehängte Dateien
Dateityp: rar bufferedstream_713.rar (183,6 KB, 10x aufgerufen)
„Software wird schneller langsamer als Hardware schneller wird. “ (Niklaus Wirth, 1995)

Mein Netzwerktool: Lan.FS
  Mit Zitat antworten Zitat
Muetze1
(Gast)

n/a Beiträge
 
#10

Re: Frage zum Buffer eines Streams

  Alt 28. Jul 2007, 20:50
Aber wäre dafür nicht eine Kapselung von Memory Mapped Files (MMF) besser geeignet? Vor allem weniger Aufwand und dabei Erfüllung aller deiner Anforderungen...
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 1 von 4  1 23     Letzte »    


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 03:00 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