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
 
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, 19: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
 


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