![]() |
Frage zum Buffer eines Streams
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 |
Re: Frage zum Buffer eines Streams
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? |
Re: Frage zum Buffer eines Streams
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 |
Re: Frage zum Buffer eines Streams
Und was ist deine Zielvariable?
Also für string dürfte es so aussehen:
Delphi-Quellcode:
Ähnlich sieht es für arrays aus.
setlength(s,30);
stream1.read(s[1],10); stream2.read(s[11],10); stream3.read(s[21],10); |
Re: Frage zum Buffer eines Streams
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?
|
Re: Frage zum Buffer eines Streams
*push* ;)
|
Re: Frage zum Buffer eines Streams
Du musst nicht nur pushen, sondern deine Frage mal genauer stellen, wenn bisher keiner geantwortet hat :wink:
Ich weis nämlich nicht, was du noch willst. |
Re: Frage zum Buffer eines Streams
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; |
Re: Frage zum Buffer eines Streams
Liste der Anhänge anzeigen (Anzahl: 1)
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: ![]()
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. |
Re: Frage zum Buffer eines Streams
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... :gruebel:
|
Alle Zeitangaben in WEZ +1. Es ist jetzt 01:19 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz