fpspreadsheet: Fix buffered stream reading speed issues.

git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@3904 8e941d3f-bd1b-0410-a28a-d453659cc2b4
This commit is contained in:
wp_xxyyzz
2015-01-27 19:31:57 +00:00
parent 2b0276dfbc
commit 8f3d5d471f
5 changed files with 47 additions and 20 deletions

View File

@ -10,7 +10,7 @@ program excel8write;
{$mode delphi}{$H+}
uses
Classes, SysUtils, fpspreadsheet, fpsRPN, xlsbiff8, fpsTypes, fpsHelpers;
Classes, SysUtils, fpspreadsheet, fpsRPN, xlsbiff8, fpsTypes, fpsCell;
const
Str_First = 'First';

View File

@ -60,7 +60,6 @@
</Target>
<SearchPaths>
<IncludeFiles Value="$(ProjOutDir)"/>
<OtherUnitFiles Value="C:\Users\Rik\Downloads\udata\"/>
<UnitOutputDirectory Value="lib\$(TargetCPU)-$(TargetOS)"/>
</SearchPaths>
<Parsing>

View File

@ -8447,10 +8447,18 @@ procedure TsCustomSpreadReader.ReadFromFile(AFileName: string; AData: TsWorkbook
var
InputFile: TStream;
begin
if (boBufStream in Workbook.Options) then
InputFile := TBufStream.Create(AFileName, fmOpenRead + fmShareDenyNone)
else
InputFile := TFileStream.Create(AFileName, fmOpenRead + fmShareDenyNone);
{
//<--
InputFile := TMemoryStream.Create;
TMemoryStream(InputFile).LoadFromFile(AFilename);
//--->
}
try
ReadFromStream(InputFile, AData);
finally

View File

@ -18,6 +18,8 @@ type
private
FFileStream: TFileStream;
FMemoryStream: TMemoryStream;
FFileStreamPos: Int64;
FFileStreamSize: Int64;
FBufWritten: Boolean;
FBufSize: Int64;
FKeepTmpFile: Boolean;
@ -144,10 +146,13 @@ begin
if FFileStream = nil then begin
if FFileName = '' then FFileName := ChangeFileExt(GetTempFileName, '.~abc');
FFileStream := TFileStream.Create(FFileName, FFileMode);
FFileStreamSize := FFileStream.Size;
FFileStreamPos := 0;
end;
end;
{ Reads FBufSize bytes from the stream into the buffer }
{ Reads FBufSize bytes from the stream into the buffer.
Called when reading. }
procedure TBufStream.FillBuffer;
var
p, n: Int64;
@ -156,19 +161,23 @@ begin
FMemoryStream.Clear;
FMemoryStream.Position := 0;
FFileStream.Position := p;
n := Min(FBufSize, FFileStream.Size - p);
n := Min(FBufSize, FFileStreamSize - p);
FMemoryStream.CopyFrom(FFileStream, n);
FMemoryStream.Position := 0;
FFileStream.Position := p;
FFileStream.Position := p; // The file stream ends where the memorystream begins!
FFileStreamPos := p;
end;
{ Flushes the contents of the memory stream to file }
{ Flushes the contents of the memory stream to file
Called when writing. }
procedure TBufStream.FlushBuffer;
begin
if (FMemoryStream.Size > 0) and not FBufWritten and IsWritingMode then begin
FMemoryStream.Position := 0;
CreateFileStream;
FFileStream.CopyFrom(FMemoryStream, FMemoryStream.Size);
FFileStreamPos := FFileStream.Position;
FFileStreamSize := FFileStream.Size;
FMemoryStream.Clear;
FBufWritten := true;
end;
@ -181,7 +190,8 @@ begin
if FFileStream = nil then
Result := FMemoryStream.Position
else
Result := FFileStream.Position + FMemoryStream.Position;
// Result := FFileStream.Position + FMemoryStream.Position;
Result := FFileStreamPos + FMemoryStream.Position;
end;
{ Returns the size of the stream. Both memory and file streams are considered
@ -192,14 +202,15 @@ var
begin
if IsWritingMode then begin
if FFileStream <> nil then
n := FFileStream.Size
n := FFileStreamSize
// n := FFileStream.Size
else
n := 0;
if n = 0 then n := FMemoryStream.Size;
Result := Max(n, GetPosition);
end else begin
CreateFileStream;
Result := FFileStream.Size;
Result := FFileStreamSize;
end;
end;
@ -238,6 +249,7 @@ begin
CreateFileStream;
if IsWritingMode then begin
Result := FFileStream.Read(Buffer, Count);
FFileStreamPos := FFileStream.Position;
end else begin
FillBuffer;
Result := FMemoryStream.Read(Buffer, Count);
@ -256,6 +268,7 @@ begin
FlushBuffer;
FFileStream.Position := p;
Result := FFileStream.Read(Buffer, Count);
FFileStreamPos := p + Count;
end else begin
FillBuffer;
Result := FMemoryStream.Read(Buffer, Count);
@ -285,10 +298,12 @@ begin
CreateFileStream;
// case #2: New position is within buffer, file stream exists
if (newPos >= FFileStream.Position) and (newPos < FFileStream.Position + FMemoryStream.Size)
// if (newPos >= FFileStream.Position) and (newPos < FFileStream.Position + FMemoryStream.Size)
if (newPos >= FFileStreamPos) and (newPos < FFileStreamPos + FMemoryStream.Size)
then begin
FMemoryStream.Position := newPos - FFileStream.Position;
Result := FMemoryStream.Position;
// FMemoryStream.Position := newPos - FFileStream.Position;
FMemoryStream.Position := newPos - FFileStreamPos;
Result := newpos; //FMemoryStream.Position;
exit;
end;
@ -296,6 +311,7 @@ begin
if IsWritingMode then
FlushBuffer;
FFileStream.Position := newPos;
FFileStreamPos := newPos;
FMemoryStream.Position := 0;
if not IsWritingMode then
FillBuffer;
@ -306,17 +322,20 @@ var
savedPos: Int64;
begin
// Case #1: Bytes fit into buffer
if FMemoryStream.Position + ACount < FBufSize then begin
if FMemoryStream.Position + ACount < FBufSize then
begin
Result := FMemoryStream.Write(ABuffer, ACount);
FBufWritten := false;
exit;
end;
end else
// Case #2: Buffer would overflow
begin;
savedPos := GetPosition;
FlushBuffer;
FFileStream.Position := savedPos;
Result := FFileStream.Write(ABuffer, ACount);
FFileStreamPos := savedPos + ACount;
FFileStreamSize := FFileStream.Size;
end;
end;

View File

@ -69,6 +69,7 @@
<Unit6>
<Filename Value="internaltests.pas"/>
<IsPartOfProject Value="True"/>
<UnitName Value="internaltests"/>
</Unit6>
<Unit7>
<Filename Value="formattests.pas"/>