program Project1;
{$mode objfpc}{$H+}
{$APPTYPE CONSOLE}
uses
Windows, Classes, Bufstream, SysUtils;
type
TFileMapRead = class(TCustomMemoryStream)
private
FMapHandle: THandle;
procedure CloseMapping;
public
constructor Create(const FileName: string);
destructor Destroy; override;
end;
procedure DoReadByByte(Stream: TStream);
var
i: Integer;
begin
for i := 0 to Stream.Size - 1 do
Stream.ReadByte;
end;
procedure WriteTimeDiff(From: TDateTime);
begin
WriteLn(FormatDateTime('s.zzz" sec"', Now - From));
end;
var
Stream: TStream;
BStream: TBufStream;
Data: array of byte;
t: TDateTime;
const
FILENAME = 'testdata.dat';
N = 1000000;
constructor TFileMapRead.Create(const FileName: string);
var
FileSize: Integer;
HFile: THandle;
P: Pointer;
begin
inherited Create;
HFile := CreateFile(PChar(FileName), GENERIC_READ,
FILE_SHARE_READ, nil, OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL or FILE_FLAG_SEQUENTIAL_SCAN, 0);
if HFile = INVALID_HANDLE_VALUE then
RaiseLastOSError;
FileSize := GetFileSize(HFile, nil);
if FileSize > 0 then
begin
FMapHandle := CreateFileMapping(HFile, nil, PAGE_READONLY, 0, 0, nil);
CloseHandle(HFile);
if FMapHandle = 0 then
RaiseLastOSError;
P := MapViewOfFile(FMapHandle, FILE_MAP_READ, 0, 0, 0);
if P = nil then
RaiseLastOSError;
SetPointer(P, FileSize);
end
else
begin
CloseHandle(HFile);
SetPointer(nil, 0);
end;
end;
procedure TFileMapRead.CloseMapping;
begin
if Memory <> nil then
begin
UnmapViewOfFile(Memory);
SetPointer(nil, 0);
end;
if FMapHandle <> 0 then
begin
CloseHandle(FMapHandle);
FMapHandle := 0;
end;
end;
destructor TFileMapRead.Destroy;
begin
CloseMapping;
inherited;
end;
begin
Write('Creating test file with ', N, ' bytes...');
Stream := TFileStream.Create(FILENAME, fmCreate);
try
SetLength(Data, N); // 100 MB test file
Stream.WriteBuffer(Data[0], Length(Data));
finally
Stream.Free;
end;
WriteLn(' Done.');
Stream := TMemoryStream.Create;
try
Write('Reading byte by byte using a TMemorystream: ');
t := Now;
TMemorystream(Stream).LoadFromFile(FILENAME);
DoReadByByte(Stream);
WriteTimeDiff(t);
finally
Stream.Free;
end;
Stream := TFileStream.Create(FILENAME, fmOpenRead);
try
Write('Reading byte by byte using a TFileStream: ');
t := Now;
DoReadByByte(Stream);
WriteTimeDiff(t);
Stream.Position := 0;
BStream := TReadBufStream.Create(Stream, 1024);
try
Write('Reading byte by byte using a TReadBufStream: ');
t := Now;
DoReadByByte(Stream);
WriteTimeDiff(t);
finally
BStream.Free;
end;
finally
Stream.Free;
end;
Stream := TFileMapRead.Create(FILENAME);
try
Write('Reading byte by byte using a TFileMapRead: ');
t := Now;
DoReadByByte(Stream);
WriteTimeDiff(t);
finally
Stream.Free;
end;
DeleteFile(FILENAME);
Readln;
end.