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.