📄 gphugef.pas
字号:
Dec(count,send);
bufp := OffsetPtr(bufp,send);
end;
end
else
bufp := @buf;
if count > 0 then begin // store leftovers
Move(bufp^,OffsetPtr(hfBuffer,hfBufOffs)^,count);
Inc(hfBufOffs,count);
Inc(transferred,count);
hfBufFilePos := hfBufFileOffs+hfBufOffs;
end;
end; { TGpHugeFile.Transmit }
{:Reads 'count' number of bytes large units from a file (or buffer if access is
buffered).
@param buf Buffer for read data.
@param count Number of bytes to be read..
@param transferred (out) Number of bytes actually read..
@raises EGpHugeFile when trying to read while in buffered write mode.
@raises Various system exceptions.
@seeAlso Reset, Rewrite
}
procedure TGpHugeFile.Fetch(var buf; count: DWORD; var transferred: DWORD);
var
got : DWORD;
bufp : pointer;
read : DWORD;
trans: DWORD;
begin
if hfBufWrite then
raise EGpHugeFile.CreateFmtHelp(sReadWhileInBufferedWriteMode,[FileName],hcHFReadInBufferedWriteMode);
transferred := 0;
got := hfBufSize-hfBufOffs;
if got <= count then begin
if got > 0 then begin // read from buffer
Move(OffsetPtr(hfBuffer,hfBufOffs)^,buf,got);
transferred := got;
Dec(count,got);
hfBufFilePos := hfBufFileOffs-hfBufSize+hfBufOffs+got;
end;
bufp := OffsetPtr(@buf,got);
hfBufOffs := 0;
if count >= hfBufferSize then begin // read directly
read := (count div hfBufferSize)*hfBufferSize;
if hfHalfClosed then
trans := 0 //2.26
else if not ReadFile(hfHandle,bufp^,read,trans,nil) then
Exit;
hfBufFileOffs := hfBufFileOffs+trans;
hfBufFilePos := hfBufFileOffs;
Inc(transferred,trans);
Dec(count,read);
bufp := OffsetPtr(bufp,read);
if trans < read then
Exit; // Eof
end;
// fill the buffer
if not hfHalfClosed then begin
if LoadedToTheEOF then
hfBufSize := 0
else begin
SetLastError(0);
Win32Check(ReadFile(hfHandle,hfBuffer^,hfBufferSize,hfBufSize,nil),'Fetch');
hfBufFileOffs := hfBufFileOffs+hfBufSize;
end;
end
else begin
//3.03: when reacing end of buffer in hfHalfClosed mode, buffer must not
// be invalidated
hfBufOffs := hfBufSize;
Exit;
end;
end
else
bufp := @buf;
if count > 0 then begin // read from buffer
got := hfBufSize-hfBufOffs;
if got < count then
count := got;
if count > 0 then
Move(OffsetPtr(hfBuffer,hfBufOffs)^,bufp^,count);
Inc(hfBufOffs,count);
Inc(transferred,count);
hfBufFilePos := hfBufFileOffs-hfBufSize+hfBufOffs;
end;
end; { TGpHugeFile.Fetch }
{:Flushed file buffers (internal implementation).
@returns False if data could not be written.
}
function TGpHugeFile.FlushBuffer: boolean;
var
written: DWORD;
begin
if (hfBufOffs > 0) and hfBufWrite then begin
if hfFlagNoBuf then
hfBufOffs := RoundToPageSize(hfBufOffs);
Result := WriteFile(hfHandle,hfBuffer^,hfBufOffs,written,nil);
hfBufFileOffs := hfBufFileOffs+written;
hfBufOffs := 0;
hfBufFilePos := hfBufFileOffs;
if hfFlagNoBuf then
FillChar(hfBuffer^,hfBufferSize,0);
end
else
Result := true;
end; { TGpHugeFile.FlushBuffer }
{:Reads 'count' number of 'block size' large units (see 'blockSize' parameter
to Reset and Rewrite methods) from a file (or buffer if access is buffered).
@param buf Buffer for read data.
@param count Number of 'block size' large units to be read.
@raises EGpHugeFile on Windows errors or if not enough data could be read
from file.
@seeAlso Reset, Rewrite
}
procedure TGpHugeFile.BlockReadUnsafe(var buf; count: DWORD);
var
transferred: DWORD;
begin
BlockRead(buf,count,transferred);
if count <> transferred then begin
if hfBuffered then
raise EGpHugeFile.CreateHelp(sEndOfFile,hcHFUnexpectedEOF)
else
Win32Check(false,'BlockReadUnsafe');
end;
end; { TGpHugeFile.BlockReadUnsafe }
{:Writes 'count' number of 'block size' large units (see 'blockSize' parameter
to Reset and Rewrite methods) to a file (or buffer if access is buffered).
@param buf Data to be written.
@param count Number of 'block size' large units to be written.
@raises EGpHugeFile on Windows errors or if data could not be written
completely.
@seeAlso Reset, Rewrite
}
procedure TGpHugeFile.BlockWriteUnsafe(const buf; count: DWORD);
var
transferred: DWORD;
begin
BlockWrite(buf,count,transferred);
if count <> transferred then begin
if hfBuffered then
raise EGpHugeFile.CreateFmtHelp(sWriteFailed,[FileName],hcHFWriteFailed)
else
Win32Check(false,'BlockWriteUnsafe');
end;
end; { BlockWriteUnsafe }
function TGpHugeFile.Compress: boolean;
begin
Result := true;
if (IsUnicodeMode and DSiIsFileCompressedW(hfName)) or
((not IsUnicodeMode) and DSiIsFileCompressed(hfNameA))
then
Result := DSiCompressFile(hfHandle);
end; { Compress }
{:Returns true if file is open.
@returns True if file is open.
}
function TGpHugeFile.IsOpen: boolean;
begin
Result := hfIsOpen;
end; { TGpHugeFile.IsOpen }
{:Checks condition and creates appropriately formatted EGpHugeFile exception.
@param condition If false, Win32Check will generate an exception.
@param method Name of TGpHugeFile method that called Win32Check.
@raises EGpHugeFile if (not condition).
}
procedure TGpHugeFile.Win32Check(condition: boolean; method: string);
var
Error: EGpHugeFile;
begin
if not condition then begin
hfWindowsError := GetLastError;
if hfWindowsError <> ERROR_SUCCESS then
Error := EGpHugeFile.CreateFmtHelp(sFileFailed+
{$IFNDEF D6PLUS}SWin32Error{$ELSE}SOSError{$ENDIF},
[method, FileName, hfWindowsError, SysErrorMessage(hfWindowsError)],
hcHFWindowsError)
else
Error := EGpHugeFile.CreateFmtHelp(sFileFailed+
{$IFNDEF D6PLUS}SUnkWin32Error{$ELSE}SUnkOSError{$ENDIF},
[method, FileName],hcHFUnknownWindowsError);
raise Error;
end;
end; { TGpHugeFile.Win32Check }
{:Returns file date in Delphi format.
@returns Returns file date in Delphi format.
@raises EGpHugeFile on Windows errors.
}
function TGpHugeFile.GetDate: TDateTime;
begin
try
CheckHandle;
{$IFDEF D10PLUS}
FileAge(FileName, Result);
{$ELSE}
Result := FileDateToDateTime(FileAge(FileName));
{$ENDIF}
except
on EGpHugeFile do
raise;
on E:Exception do
raise EGpHugeFile.CreateHelp(E.Message,hcHFUnexpected);
end;
end; { TGpHugeFile.GetDate }
function TGpHugeFile.GetFileName: WideString;
begin
if IsUnicodeMode then
Result := hfName
else
Result := hfNameA;
end; { TGpHugeFile.GetFileName }
{$IFDEF VCL6}
{$WARN SYMBOL_PLATFORM OFF}
{$ENDIF}
{:Sets file date.
@param Value new file date.
}
procedure TGpHugeFile.SetDate(const Value: TDateTime);
var
err: integer;
begin
try
CheckHandle;
err := FileSetDate(hfHandle,DateTimeToFileDate(Value));
if err <> 0 then
raise EGpHugeFile.CreateFmtHelp(sFileFailed+SysErrorMessage(err),
['SetDate', FileName],hcHFWindowsError);
except
on EGpHugeFile do
raise;
on E:Exception do
raise EGpHugeFile.CreateHelp(E.Message,hcHFUnexpected);
end;
end; { TGpHugeFile.SetDate }
{$IFDEF VCL6}
{$WARN SYMBOL_PLATFORM ON}
{$ENDIF}
{:Returns true if file is loaded into the buffer up to the last byte.
@returns Returns true if file is loaded into the buffer up to the last byte.
}
function TGpHugeFile.LoadedToTheEOF: boolean;
begin
Result := (hfBufFileOffs >= (_FileSize*hfBlockSize));
end; { TGpHugeFile.LoadedToTheEOF }
{:Returns file size. If available, returns cached size.
@returns File size in bytes.
@raises EGpHugeFile on Windows errors.
}
function TGpHugeFile._FileSize: HugeInt;
begin
if hfCachedSize < 0 then
hfCachedSize := FileSize;
Result := hfCachedSize;
end; { TGpHugeFile._FileSize }
{:Initializes buffer for writing.
}
procedure TGpHugeFile.InitWriteBuffer;
begin
hfBufSize := 0;
hfBufOffs := 0;
hfBufFileOffs := 0;
hfBufWrite := true;
end; { TGpHugeFile.InitWriteBuffer }
{:Initializes buffer for reading.
}
procedure TGpHugeFile.InitReadBuffer;
begin
hfBufOffs := 0;
hfBufSize := 0;
hfBufFileOffs := 0;
hfBufWrite := false;
end; { TGpHugeFile.InitReadBuffer }
procedure TGpHugeFile.InternalCreateEx(FlagsAndAttributes: DWORD; DesiredAccess: DWORD;
DesiredShareMode: DWORD);
begin
hfBlockSize := 1;
hfBuffer := nil;
hfBuffered := false;
hfCachedSize := -1;
hfDesiredAcc := DesiredAccess;
hfDesiredShareMode := DesiredShareMode;
hfShareModeSet := true;
hfFlagNoBuf := ((FILE_FLAG_NO_BUFFERING AND FlagsAndAttributes) <> 0);
hfFlags := FlagsAndAttributes;
hfHandle := INVALID_HANDLE_VALUE;
end; { TGpHugeFile.InternalCreateEx }
function TGpHugeFile.IsUnicodeMode: boolean;
begin
Result := (hfNameA = '');
end; { TGpHugeFile.IsUnicodeMode }
{ TGpHugeFileStream }
{:Initializes stream and opens file in required access mode.
@param fileName Name of file to be accessed.
@param access Required access mode.
@param openOptions Set of possible open options.
}
constructor TGpHugeFileStream.Create(const fileName: string;
access: TGpHugeFileStreamAccess; openOptions: THFOpenOptions;
desiredShareMode: DWORD; diskLockTimeout, diskRetryDelay: integer);
begin
inherited Create;
hfsExternalHF := false;
case access of
accRead:
begin
hfsFile := TGpHugeFile.CreateEx(fileName, FILE_ATTRIBUTE_NORMAL, GENERIC_READ, desiredShareMode);
hfsFile.Win32Check(hfsFile.ResetEx(1,0,diskLockTimeout,diskRetryDelay,openOptions) = hfOK, 'Reset');
end; //accRead
accWrite:
begin
hfsFile := TGpHugeFile.CreateEx(fileName, FILE_ATTRIBUTE_NORMAL, GENERIC_WRITE, desiredShareMode);
hfsFile.Win32Check(hfsFile.RewriteEx(1,0,diskLockTimeout,diskRetryDelay,openOptions) = hfOK, 'Rewrite');
end; //accWrite
accReadWrite:
begin
hfsFile := TGpHugeFile.CreateEx(fileName, FILE_ATTRIBUTE_NORMAL, GENERIC_READ+GENERIC_WRITE, desiredShareMode);
hfsFile.Win32Check(hfsFile.ResetEx(1,0,diskLockTimeout,diskRetryDelay,openOptions) = hfOK, 'Reset');
end; // accReadWrite
accAppend:
begin
hfsFile := TGpHugeFi
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -