{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(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=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-NumWrite0 then; MyIOResult:=0; If ISOpen then Begin If (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 '+Pad2Right(FO.GetFullPath,' ',30)+ Pad2Left(CommaStr(FO.GetSize),' ',12)+' '+ DateStr(FO.GetDate)+' '+ TimeStr(FO.GetDate)+' '); {show attributes too!} ShowFile; FO.FNext; End; End.