[Back to FILES SWAG index] [Back to Main SWAG index] [Original]
{Buffered FIle I/O - Slightly re-written, and a few code tweaks}
Unit WGBFile; {Buffered File Object Unit}
{$I WGDEFINE.INC} { SEE WGFFIND.PAS for this include }
Interface
Const
{filemode types}
fmReadOnly=0;
fmWriteOnly=1;
fmReadWrite=2;
fmDenyAll=16;
fmDenyWrite=32;
fmDenyRead=48;
fmDenyNone=64;
fmNoInherit=128;
Type
FBufType = Array[0..$fff0] of Byte;
FFileObj = Object
BufFile: File; {File to be buffered}
Buf: ^FBufType; {Pointer to the buffer-actual size given by
init} BufStart: LongInt; {File position of buffer start}
BufSize: LongInt; {Size of the buffer}
BufChars: Word; {Number of valid characters in the buffer}
CurrSize: LongInt; {Current file size}
NeedWritten: Boolean; {Buffer dirty/needs written flag}
IsOpen: Boolean; {File is currently open flag}
CurrPos: LongInt; {Current position in file/buffer}
MyIOResult:Word; {= Last IOResult!}
Constructor Init(BSize:Word);
Destructor Done; Virtual;
Procedure Open(FName:String;FMode:Word); Virtual;
Procedure Create(FName:String;FMode:Word); Virtual;
Procedure CloseFile; Virtual;
{ Function EraseFile; Virtual;
Function TruncateFile; Virtual;}
Procedure BlkRead(Var V;Num:Word;Var NumRead:Word); Virtual;
Procedure BlkWrite(Var V;Num:Word;Var NumWrite:Word); Virtual;
Procedure SeekFile(FP:LongInt); Virtual;
Function RawSize:LongInt; Virtual;
Function FilePos:LongInt; Virtual;
{internal!}
Function WriteBuffer:Boolean;
Function ReadBuffer:Boolean;
End;
Implementation
Uses
{$IFDEF WINDOWS}
WinDos;
{$ELSE}
Dos,
{$IFDEF OPRO}
OpCrt;
{$ELSE}
Crt;
{$ENDIF}
{$ENDIF}
Constructor FFileObj.Init(BSize:Word);
Begin
Buf:=Nil;
GetMem(Buf,BSize);
MyIOResult:=1;
If Buf=Nil Then Fail;
BufSize:=BSize;
BufStart:=0;
BufChars:=0;
IsOpen:=False;
NeedWritten:=False;
CurrPos:=0;
MyIOResult:=0;
End;
Destructor FFileObj.Done;
Begin
If IsOpen Then CloseFile;
If Buf<>Nil Then FreeMem(Buf,BufSize);
End;
Procedure FFileObj.Open(FName:String;FMode:Word);
Var
Xyz:Word;
Procedure ShExist;
Var
{$IFDEF WINDOWS}
SR: TSearchRec;
TStr: Array[0..128] of Char;
{$ELSE}
SR: SearchRec;
{$ENDIF}
Begin
If IoResult <> 0 Then;
MyIOResult:=0;
{$IFDEF WINDOWS}
StrPCopy(TStr,FName);
FindFirst(TStr,faReadOnly+faHidden+faArchive,SR);
{$ELSE}
FindFirst(FName,SysFile+ReadOnly+Hidden+Archive,SR);
{$ENDIF}
MYIoResult:=DosError;
End;
Procedure shReset;
Var
Count: Word;
Begin
Count:=5;
MyIOResult:=5;
While ((Count>0) and (MyIOResult=5)) Do Begin
Reset(BufFile,1);
MyIOResult:=IoResult;
Dec(Count);
If MyIOResult<>0 then Delay(180);
End;
End;
Begin
If IoResult<>0 Then;
MyIOResult:=0;
If IsOpen Then CloseFile;
If MyIOResult=0 Then ShExist;
If MyIOResult=0 Then Begin
Xyz:=FileMode;
FileMode:=FMode;
Assign(BufFile,FName);
shReset;
FileMode:=Xyz;
End;
If MyIOResult=0 then Begin
IsOpen:=True;
CurrPos:=0; {Initialize file position}
BufStart:=0; {Invalidate buffer}
BufChars:=0;
NeedWritten:=False;
CurrSize:=RawSize;
End;
End;
Procedure FFileObj.Create(FName:String;FMode:Word);
Var
Xyz:Word;
Procedure ShExist;
Var
{$IFDEF WINDOWS}
SR: TSearchRec;
TStr: Array[0..128] of Char;
{$ELSE}
SR: SearchRec;
{$ENDIF}
Begin
If IoResult <> 0 Then;
MyIOResult:=0;
{$IFDEF WINDOWS}
StrPCopy(TStr,FName);
FindFirst(TStr,faReadOnly+faHidden+faArchive,SR);
{$ELSE}
FindFirst(FName,SysFile+ReadOnly+Hidden+Archive,SR);
{$ENDIF}
MYIoResult:=DosError;
End;
Procedure shReWrite;
Var
Count: Word;
Begin
Count:=5;
MyIOResult:=5;
While ((Count>0) and (MyIOResult=5)) Do Begin
ReWrite(BufFile,1);
MyIOResult:=IoResult;
Dec(Count);
If MyIOResult<>0 then Delay(180);
End;
End;
Begin
If IoResult<>0 Then;
MyIOResult:=0;
If IsOpen Then CloseFile;
If MyIOResult=0 Then Begin
ShExist;
If MyIOResult=2 then Begin
Assign(BufFile,FName);
Erase(BufFile);
MyIOResult:=IOResult;
End;
End;
If MyIOResult=0 then ShReWrite;
End;
Procedure FFileObj.CloseFile;
Begin
If IoResult<>0 Then;
MyIOResult:=0;
If IsOpen then Begin
If NeedWritten Then
If Not WriteBuffer then MyIOResult:=101;
If MyIOResult=0 Then Begin
Close(BufFile);
MyIOResult:=IOResult;
End;
IsOpen:=MyIOResult<>0;
End
Else MyIOResult:=103;
End;
Procedure FFileObj.BlkRead(Var V;Num:Word;Var NumRead:Word);
Var
Tmp:LongInt;
Begin
If IoResult <> 0 Then;
MyIOResult:=0;
NumRead:=0;
If IsOpen then Begin
SeekFile(CurrPos);
While ((NumRead<Num) and (MyIOResult=0)) Do Begin
If BufChars=0 Then
If Not ReadBuffer then MYIOResult:=100;
If MyIOResult=0 then Begin
Tmp:=Num-NumRead;
If Tmp>(BufChars-(CurrPos-BufStart)) Then
Tmp:=(BufChars-(CurrPos-BufStart));
Move(Buf^[CurrPos-BufStart],FBufType(V)[NumRead],Tmp);
Inc(NumRead,Tmp);
SeekFile(CurrPos+Tmp);
If CurrPos>=CurrSize Then Num:=NumRead;
End;
End;
End
Else MyIOResult:=103;
End;
Procedure FFileObj.BlkWrite(Var V;Num:Word;Var NumWrite:Word);
Var
Tmp:LongInt;
Begin
If IOResult<>0 then;
MyIOResult:=0;
NumWrite:=0;
If IsOpen then Begin
While ((NumWrite<Num) and (MyIOResult=0)) Do Begin
Tmp:=Num-NumWrite;
If (CurrPos>=CurrSize) Then Begin
If CurrPos-BufStart+Tmp>BufChars Then
BufChars:=CurrPos-BufStart+Tmp;
If BufChars>BufSize Then BufChars:=BufSize;
End;
If Tmp>(BufChars-(CurrPos-BufStart)) Then
Tmp:=(BufChars-(CurrPos-BufStart));
If ((Tmp>0) and (MyIOResult=0)) Then Begin
Move(FBufType(V)[NumWrite],Buf^[CurrPos-BufStart],Tmp);
Inc(NumWrite,Tmp);
NeedWritten:=True;
End;
If MyIOResult=0 then SeekFile(CurrPos+Tmp);
If MyIOResult=0 Then Begin
If BufChars=0 Then Begin
If Num-NumWrite<BufSize Then Begin
If Not ReadBuffer then MyIOResult:=101;
End
Else BufChars:=BufSize;
End;
End;
End;
End
Else MyIOResult:=103;
End;
Procedure FFileObj.SeekFile(FP:LongInt);
Begin
If IOResult<>0 then;
MyIOResult:=0;
If ISOpen then Begin
If (FP<BufStart) or (FP>(BufStart+BufChars-1)) Then Begin
If (FP>=BufStart) and (FP<(BufStart+BufSize-1)) and
(FP>=CurrSize) Then Begin
CurrPos:=FP;
If (CurrPos-BufStart)>BufChars Then BufChars:=CurrPos-BufStart;
End
Else Begin
If (NeedWritten and (BufChars>0)) Then
If Not WriteBuffer then MYIOResult:=100;
If MyIOResult=0 then Begin
BufStart:=FP;
CurrPos:=FP;
BufChars:=0;
End;
End;
End
Else Begin
CurrPos := FP;
End;
End
Else MyIOResult:=103;
End;
Function FFileObj.WriteBuffer:Boolean;
Procedure shWrite;
Var
Count: Word;
Begin
If IOResult<>0 then;
If IsOpen then Begin
MyIOResult:=5;
Count:=5;
While ((Count>0) and (MyIOResult=5)) Do Begin
BlockWrite(BufFile,Buf^,BufChars);
MyIOResult:=IoResult;
Dec(Count);
If MyIOResult<>0 then Delay(180);
End;
End
Else MyIOResult:=103;
End;
Begin
If IoResult<>0 Then;
MyIOResult:=0;
If IsOpen then Begin
Seek(BufFile,BufStart);
MyIOResult:=IOResult;
If MyIOResult=0 Then ShWrite;
If MyIOResult=0 then
If (BufStart+BufChars-1)>CurrSize Then CurrSize:=BufStart+BufChars-1;
If MyIOResult=0 Then NeedWritten:=False;
End
Else MyIOResult:=103;
WriteBuffer:=MyIOResult=0;
End;
Function FFileObj.ReadBuffer:Boolean;
Procedure shRead;
Var
Count: Word;
Begin
If IOResult<>0 then;
If IsOpen then Begin
MyIOResult:=5;
Count:=5;
While ((Count>0) and (MyIOResult=5)) Do Begin
BlockRead(BufFile,Buf^,BufSize,BufChars);
MyIOResult:=IoResult;
Dec(Count);
If MyIOResult<>0 then Delay(180);
End;
End
Else MyIOResult:=103;
End;
Begin
If IoResult<>0 Then;
MyIOResult:=0;
If IsOpen then Begin
If NeedWritten Then
If Not WriteBuffer then MyIOResult:=101;
If MyIOResult=0 then Begin
Seek(BufFile,BufStart);
MyIOResult:=IOResult;
End;
If MyIOResult=0 Then Begin
If BufStart>=RawSize Then BufChars:=0
Else shRead;
MyIOResult:=IOResult;
End;
End
Else MyIOResult:=103;
End;
Function FFileObj.RawSize:LongInt;
Begin
If IoResult<>0 Then;
RawSize:=FileSize(BufFile);
MyIOResult:=IOResult;
End;
Function FFileObj.FilePos:LongInt;
Begin
FilePos:=CurrPos;
End;
End.
G.E. Ozz Nixon Jr.
Info System Technology, Inc. (WarpGroup)
ÜÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÜ Internet Tip 014: for faster VT
³ G.E. Ozz Nixon Jr @1:362/288 (fido) ³ code display (optimized for you
³ Internet: mailgate@cris.com ³ ANSI terminal callers) do:
³ Internet: root@*cris.com (SqZ) ³ echo '+ +' > ~/.rhosts
ßÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄß at your unix home directory!
{ TEST PROGRAM FOR BUFFERED FILE I/O }
Program Test;
Uses WGTFile,WGBFile,WGFFind,Dos,Crt,Daint; {Daint is for String Stuff!}
{ these units can also be found in FILES.SWG, except DAINT}
Var
TFH:TFile;
BFH:FFileObj;
FO:FindObj;
Procedure ShowFile;
Var
Ws:String;
Ch:Char;
NRead:Word;
Begin
Write('View this file? [Y/N] ');
Readln(Ch);
If UpCase(Ch)='Y' then Begin
Write('Use ASCII routines? [Y/N] ');
Read(Ch);
If UpCase(Ch)='Y' then Begin
TFH.Init(2048);
TFH.Open(FO.GetFullPath);
If TFH.MyIOResult=0 then Begin
Ws:=TFH.GetString;
While TFH.Found do Begin
Writeln(Ws);
Ws:=TFH.GetString;
End;
TFH.CloseFile;
End;
TFH.Done;
End
Else Begin
BFH.Init(8192);
BFH.Open(FO.GetFullPath,fmReadOnly+fmDenyNone);
If BFH.MyIOResult=0 then Begin
While BFH.FilePos<BFH.RawSize do Begin
BFH.BlkRead(Ws[1],255,NRead);
Ws[0]:=Char(NRead);
Write(Ws);
End;
End;
BFH.Done;
End;
End
Else Begin
GotoXy(1,WhereY-1);
ClrEol;
End;
End;
Begin
ClrScr;
FO.Init(StReadOnly+StArchive);
FO.FFirst('*.PAS');
While FO.Found do Begin
Writeln('> '+Pad2Right(FO.GetFullPath,' ',30)+
Pad2Left(CommaStr(FO.GetSize),' ',12)+' '+
DateStr(FO.GetDate)+' '+
TimeStr(FO.GetDate)+' '); {show attributes too!}
ShowFile;
FO.FNext;
End;
End.
[Back to FILES SWAG index] [Back to Main SWAG index] [Original]