home *** CD-ROM | disk | FTP | other *** search
- UNIT U_EGB_0a; {Last mod by JFH on 07/20/95}
-
- { DEFINITION OF SOME BASIC FILE IO CLASSES }
-
- { Includes:
- tBufferedFileScanner -- Buffered file reader class returns a
- pointer to data in its buffer.
- tBufTextFileScanner -- Text file reader class returns a pointer
- to data in its buffer. The text records can be longer than
- a string type can hold.
- tBufTextStringFileReader -- Uses tBufTextFileScanner to return an
- actual string rather than a pointer.
- t123RecScanner -- This reads the type-length word record header
- system of Lotus. (I have found this useful for several
- applications.)
-
- { What could have been included:
- (1) Buffered file reader for returning the data rather than a
- pointer.
- (2) An abstract type that would have taken an byte position within
- the file and a number of bytes to be fetched and returned a
- pointer or the data.
- (3) A simple version controlled fixed length record file system
- that would allow the records to have new fields added to the
- end of the records, such that new programs could read old data
- and new data could be used by old programs.
- (4) A partitioned file system that would all navagating through
- huge variable length record files without having to scan record
- by record.
-
- { Pgm. 07/15/95 by John F Herbster }
-
- {=====} interface {====================================================}
-
- USES SysUtils; {for pByteArray and tFilename}
-
- TYPE
- tBufferedFileScanner = class
- Constructor Create
- (const aPath: tFilename; aSizeOfClusters,aMaxRecLgh: word);
- { creates the object to read file named in aPath, gets a buffer,
- opens the file, and sets up the pointers. }
- Function EOF: boolean;
- { rtns true if the read position is at or beyond the end of file.}
- Function LocNextFixedLghRec
- (var pRec: pByteArray; const NbrReqd: word): boolean;
- { brings the next NbrReqd bytes of data into its buffer and rtns
- true and a byte array pointer to the data if found. The data
- itself is not transfered and the pointer will be invalid after
- another call to this object. If all of the requested data can-
- not be found, then false is returned. }
- Function LocNextVarLghRec
- (var pRec: pByteArray; var NbrFound: word): boolean; virtual;
- { brings in up to the MaxLghRec number of bytes of data into its
- buffer and if at least one byte was found, then rtns true, a
- byte array pointer to the data, and the number of bytes found,
- up to the MaxLghRec number. The data itself is not transfered
- and the pointer will be invalid after another call to this
- object. If all of the requested data cannot be found, then
- false is returned. }
- Destructor Destroy; override;
- protected
- Chan: file;
- SizeOfFile, fPrevPos, fCurPos: longint;
- SizeOfCluster, MaxLghRec, SizeOfBuf, DataLimInBuf,
- PrevIndex,CurIndex: word;
- pBuf: pByteArray;
- Procedure RefillBuffer;
- end;
-
- TYPE
- tBufTextFileScanner = class (tBufferedFileScanner)
- LnNbr: longint;
- Constructor Create
- (const aPath: tFilename; aSizeOfClusters,aMaxRecLgh: word);
- { creates the object to read text file named in aPath, gets a
- buffer, opens the file, and sets up the pointers. }
- Function LocNextVarLghRec
- (var pRec: pByteArray; var NbrFound: word): boolean; override;
- { brings in up to the MaxLghRec number of bytes of data into its
- buffer and searches for the CR. If the CR was found, then rtns
- true, a byte array pointer to the data, and the number of bytes
- found, not including the CR. The data itself is not transfered
- and the pointer will be invalid after another call to this
- object. If a CR cannot be found with in the MaxLghRec number
- of bytes then false is returned. (Note possible problem here
- if last line has no last CR!!)}
- end;
-
- TYPE
- tBufTextStringFileReader = class (tBufTextFileScanner)
- Constructor Create
- (const aPath: tFilename; aSizeOfClusters: word);
- { creates the object to read text file named in aPath, gets a
- buffer, opens the file, and sets up the pointers. }
- Function GotLine (var Line: string): boolean;
- { brings in up to 256 bytes of data into the buffer and searches
- for the CR. If the CR was found, then rtns true and the line
- found, not including the CR or LF in a Pascal string. If a CR
- cannot be found with in the 256 bytes then false is returned.
- (Note possible problem here if last line has no last CR!!)}
- end;
-
- TYPE
- t123Header = record RecTypeH, RecLghH: word end;
- p123Header = ^t123Header;
- tBuf123RecScanner = class (tBufferedFileScanner)
- Constructor Create
- (const aPath: tFilename; aBufferSize, MaxLghRec: word);
- { creates the object to read text file named in aPath, gets a
- buffer, opens the file, and sets up the pointers. }
- Function LocNextRec
- (var RecType, RecLgh: word; var pRec: pByteArray): boolean;
- { brings in up to MaxLghRec bytes into buffer and returns the
- type of the record, the length of the record, and pointer to
- the data part of the record (just past header). }
- end;
-
- {=====} IMPLEMENTATION {===============================================}
-
- Constructor tBufferedFileScanner.Create
- (const aPath: tFilename; aSizeOfClusters,aMaxRecLgh: word);
- Begin
- Inherited Create;
- Assign (Chan,aPath); Reset(Chan,1); SizeOfFile:=FileSize(Chan);
- SizeOfCluster:=aSizeOfClusters; MaxLghRec:=aMaxRecLgh;
- SizeOfBuf:=SizeOfCluster+MaxLghRec; GetMem(pBuf,SizeOfBuf);
- End;
-
- Destructor tBufferedFileScanner.Destroy;
- Begin
- If SizeOfBuf>0
- then FreeMem(PBuf,SizeOfBuf);
- Inherited Destroy;
- End;
-
- Function tBufferedFileScanner.EOF: boolean;
- Begin Result:=fCurPos<SizeOfFile End;
-
- Procedure tBufferedFileScanner.RefillBuffer;
- Var n,i: word;
- Begin
- n:=DataLimInBuf-CurIndex; {# bytes to move}
- i:=MaxLghRec-n; {Dest. for first}
- If n>0 then Move(pBuf^[CurIndex],pBuf^[i],n);
- CurIndex:=i; {New buffer index}
- BlockRead(Chan,pBuf^[MaxLghRec],SizeOfCluster,n);
- DataLimInBuf:=MaxLghRec+n; {New limit of data in buf.}
- End;
-
- Function tBufferedFileScanner.LocNextFixedLghRec
- (var pRec: pByteArray; const NbrReqd: word): boolean;
- Begin
- If (fCurPos<0) or (fCurPos+NbrReqd>SizeOfFile)
- then begin Result:=false; EXIT end;
- If CurIndex+NbrReqd>DataLimInBuf
- then RefillBuffer;
- fPrevPos:=fCurPos; fCurPos:=fCurPos+NbrReqd;
- PrevIndex:=CurIndex; CurIndex:=CurIndex+NbrReqd;
- Result:=true;
- pRec:=@pBuf^[PrevIndex];
- End;
-
- Function tBufferedFileScanner.LocNextVarLghRec
- (var pRec: pByteArray; var NbrFound: word): boolean;
- Begin
- If (fCurPos<0) or (fCurPos+1>SizeOfFile)
- then begin Result:=false; EXIT end;
- If CurIndex+MaxLghRec>DataLimInBuf
- then RefillBuffer;
- If DataLimInBuf-CurIndex<MaxLghRec
- then NbrFound:=DataLimInBuf-CurIndex
- else NbrFound:=MaxLghRec;
- PrevIndex:=CurIndex; CurIndex:=CurIndex+NbrFound;
- fPrevPos:=fCurPos; fCurPos:=fCurPos+NbrFound;
- Result:=true;
- pRec:=@pBuf^[PrevIndex];
- End;
-
- Constructor tBufTextFileScanner.Create
- (const aPath: tFilename; aSizeOfClusters,aMaxRecLgh: word);
- Begin Inherited Create(aPath,aSizeOfClusters,aMaxRecLgh+2) End;
-
- Function tBufTextFileScanner.LocNextVarLghRec
- (var pRec: pByteArray; var NbrFound: word): boolean;
- Var n,i,j: word; Const CR=byte(^M); LF=byte(^J);
- Begin
- If Inherited LocNextVarLghRec(pRec,n)
- then begin {Scan for the CR-LF.}
- i:=PrevIndex; j:=i+n; {Limit for search.}
- While (i<j) and (pBuf^[i]<>CR) do inc(i); {Inc till at CR}
- If i>=j {Past the end?}
- then begin {If not located, then revert to previous pos.}
- Result:=false;
- CurIndex:=PrevIndex; fCurPos:=fPrevPos;
- end
- else begin
- Result:=true; Inc(LnNbr);
- NbrFound:=i-PrevIndex; CurIndex:=PrevIndex+NbrFound+1;
- If (CurIndex<DataLimInBuf) and (pBuf^[CurIndex]=LF)
- then inc(CurIndex); {Allow LF to be optional.}
- fCurPos:=fPrevPos+(CurIndex-PrevIndex);
- end;
- end
- else Result:=false;
- End;
-
- Constructor tBufTextStringFileReader.Create
- (const aPath: tFilename; aSizeOfClusters: word);
- Begin Inherited Create(aPath,aSizeOfClusters,256) End;
-
- Function tBufTextStringFileReader.GotLine (var Line: string): boolean;
- { brings in up to 256 bytes of data into the buffer and searches
- for the CR. If the CR was found, then rtns true and the line
- found, not including the CR or LF in a Pascal string. If a CR
- cannot be found with in the 256 bytes then false is returned.
- (Note possible problem here if last line has no last CR!!)}
- Var pRec: pByteArray; NbrFound: word;
- Begin
- If LocNextVarLghRec(pRec,NbrFound)
- then begin
- Result:=true;
- byte(Line[0]):=NbrFound;
- Move(pRec^,Line[1],NbrFound);
- end
- else Result:=false;
- End;
-
- Constructor tBuf123RecScanner.Create
- (const aPath: tFilename; aBufferSize, MaxLghRec: word);
- { creates the object to read text file named in aPath, gets a
- buffer, opens the file, and sets up the pointers. }
- Begin
- Inherited Create(aPath,aBufferSize,MaxLghRec+SizeOf(t123Header));
- End;
-
- Function tBuf123RecScanner.LocNextRec
- (var RecType, RecLgh: word; var pRec: pByteArray): boolean;
- { brings in up to MaxLghRec bytes into buffer and returns the
- type of the record, the length of the record, and pointer to
- the data part of the record (just past header). }
- Var p: pByteArray; n: word;
- Begin
- If LocNextVarLghRec(p,n)
- then with p123Header(p)^ do begin
- If RecLghH<=n-2
- then begin
- Result:=true;
- RecType:=RecTypeH;
- RecLgh:=RecLghH;
- fCurPos:=fPrevPos+RecLgh+SizeOf(t123Header);
- CurIndex:=PrevIndex+RecLgh+SizeOf(t123Header);
- pRec:=@pByteArray(p)^[SizeOf(t123Header)];
- end
- else Result:=false;
- end
- else Result:=false;
- End;
-
- {=====} end. {=========================================================}
-
-