ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ» º º º FileRead Programmer's Library 1.0 º º º ÌÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ͹ º º º Copyright 1992, Tom Clancy º º All Rights Reserved º º º ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ INTRODUCTION The FileRead programmer's library is a set of tools that allow you, the programmer, to open and manipulate a data file with any data type you choose. It's fully object oriented and extensible so using this database is as easy as declaring an instance of the TFread object, initializing the file, then manipulating the data. SHAREWARE NOTICE FileRead is shareware, not freeware, and a donation of $20.00 is asked for the registration and use of this product. This is a programmer's tool. I require no special registration for commercial use or for use in a software company, as long as the product is registered under that company's name and this toolkit is used for developing software, either for commercial use or in-house, specifically for that company. REQUIREMENTS This toolkit requires Turbo Pascal 6.0 and will work on anything that Turbo Pascal 6.0 will work on, including my lowly tandy 1000 SX, the computer on which I designed FileRead. FILES You should have the following files in your distribution disk or archive: Fileread.Pas........The fileread library source code Fileread.Tpu........The fileread library Tpu version 6 format Fileread.Txt........This documentation Test.Pas............Test #1 source code Test2.Pas...........Test #2 source code L.Exe...............File listing program Readme.Bat..........Batch file to launch file viewer Register.Doc........Registration form to be filled out and sent in If you do not have the complete set of files, then either notify the sysop of the board from which you downloaded it, or, when you send in the registration, you will receive a new disk with the latest version. If you do not have all the files in your archive and would like to have the full version for evaluation before registering, then call me or send me a letter and we'll work out a way to get you the complete set of files. METHOD AND OBJECT SUMMARY The following is the FileRead object and a description of each method plus example source code on how to use each method. *********************************************************************** TFreadPtr = ^TFreadObj; {Pointer to the TFread object} TFreadObj = Object Constructor Init(fn : string; mode:integer; recsize : longint); Destructor Done; { random access methods. } Procedure ReadRec(var frec; fpos:longint); virtual; Procedure WriteRec(var frec; fpos:longint); virtual; { sequential access methods. } Procedure AppendRec(var frec); Procedure ReadNext(var frec); Procedure ReadPrevious(var frec); Procedure ReadCurrent(var frec); { various file modification methods. } Procedure EraseFile; Function RenameFile(fn:string):boolean; { miscellaneous functions and error flag functions. } Procedure Rewind; Function NumRecs : Longint; Function GetFilename : String; Function GetCurrent : Longint; Function OpenError : boolean; Function ReadError : boolean; Function WriteError : boolean; End; *********************************************************************** Constructor Init(fn : string; mode:integer; recsize : longint); The constructor takes, as its parameters, the filename in a String format, the mode for which TFread will initialize the file with, and the size of the records that will be stored in and retrieved from the file. The file name can be a single filename such as INFO.DAT, or it can handle a path, such as C:\DATABASE\DATA\INFO.DAT. The mode can be one of three choice, OPEN, CREATE, or OPENCREATE. OPEN will attempt to open the file. If the file does not exist, then the OpenError flag will be set. CREATE will attempt to create the file whether or not it exists. If the file does exist, then it will be rewritten, unallocating the data that was previously in the file. If it cannot create the file for some reason, then the OpenError flag will be set. OPENCREATE will first attempt to open the file specified. If the file does not exist, TFread will then attempt to create the file. If the file, for some reason, cannot be created, then the OpenError flag will be set. Example: Type InfoRec : Record Name : String[25]; Address : String[25]; City : String[25]; State : String[2]; ZipCode : String[5]; end; Procedure DoSomething; Var MyFile : TFreadPtr; {a pointer to the TFread object} Info : InforRec; Begin New(MyFile,Init('TEST.DAT',OpenCreate,SizeOf(InfoRec))); . . . End; ---------------------------------------------------------------------------- Destructor Done; The destructor will close the file, setting the OpenError flag to true so that you cannot access any of the methods. Example: Type InfoRec : Record Name : String[25]; Address : String[25]; City : String[25]; State : String[2]; ZipCode : String[5]; end; Procedure DoSomething; Var MyFile : TFreadPtr; {a pointer to the TFread object} Info : InforRec; Begin New(MyFile,Init('TEST.DAT',OpenCreate,SizeOf(InfoRec))); . . . Dispose(MyFile,Done); End; ---------------------------------------------------------------------------- Procedure ReadRec(var frec; fpos:longint); ReadRec will read a record at the specified location, returning it in the variable frec. If an invalid File Position (fpos) is passed to the procedure, or if for some reason ReadRec could not access the file data at the specified location, then the ReadError flag will be set. Example: Type InfoRec : Record Name : String[25]; Address : String[25]; City : String[25]; State : String[2]; ZipCode : String[5]; end; Procedure DoSomething; Var MyFile : TFreadPtr; {a pointer to the TFread object} Info : InforRec; Begin New(MyFile,Init('TEST.DAT',OpenCreate,SizeOf(InfoRec))); MyFile^.ReadRec(Info,0); {Read the first record in the data file} Dispose(MyFile,Done); End; ---------------------------------------------------------------------------- Procedure WriteRec(var frec; fpos:longint); WriteRec will write a record passed in as Frec at the file position pointed to by fpos. If the file position passed to WriteRec is invalid or if for some reason WriteRec cannot write a record at the specified location, then the WriteError flag will be set. Example: Type InfoRec : Record Name : String[25]; Address : String[25]; City : String[25]; State : String[2]; ZipCode : String[5]; end; Procedure DoSomething; Var MyFile : TFreadPtr; {a pointer to the TFread object} Info : InforRec; Begin New(MyFile,Init('TEST.DAT',OpenCreate,SizeOf(InfoRec))); with info do begin Name:='Tom Clancy'; Address:='5861 Horseshoe Drive'; City:='Bethel Park'; State:='PA'; ZipCode:='15102'; end; MyFile^.WriteRec(Info,10); {Update the 10th record in the file} MyFile^.ReadRec(Info,10); {Read the 10th record from in data file} Dispose(MyFile,Done); End; ---------------------------------------------------------------------------- Procedure AppendRec(var frec); AppendRec is a sequential access method for appending records to the end of the data file. Like WriteRec, if AppendRec cannot append a record to the file, the WriteError flag will be set. Example: Type InfoType : Word; {A file of unsigned integers!} Procedure DoSomething; Var MyFile : TFreadPtr; {a pointer to the TFread object} Info : InfoType; i : integer; Begin New(MyFile,Init('TEST.DAT',OpenCreate,SizeOf(InfoType))); Randomize; {randomize the random seed} {append 100 integers to the data file.} for i:=1 to 100 do begin Info:=Random(65535); MyFile^.AppendRec(Info); end; Dispose(MyFile,Done); End; ---------------------------------------------------------------------------- Procedure ReadNext(var frec); ReadNext will read the next record in the file and return that record in the frec variable. If ReadNext tries to read past the end of the file or if ReadNext gets an error when trying to read the next record in the file then the ReadError flag will be set. Example: Type InfoType : Word; {A file of unsigned integers!} Procedure DoSomething; Var MyFile : TFreadPtr; {a pointer to the TFread object} Info : InfoType; i : integer; Begin New(MyFile,Init('TEST.DAT',OpenCreate,SizeOf(InfoType))); MyFile^.ReadRec(Info,0); {Start at first record!} {Read and display the 100 words created in the previous example. When ReadError is set to true, we will have reached the end of the file.} while not MyFile^.ReadError do begin writeln(Info); Myfile^.Readnext(Info); end; Dispose(MyFile,Done); End; ---------------------------------------------------------------------------- Procedure ReadPrevious(var frec); ReadPrevious, like ReadNext, is a sequential file accessing method, but instead of reading forward in the file, it will read backwards through the file, returning the previous record in the frec variable. The ReadError flag will be set if ReadPrevious attempts to read a record that's one less than the first record or if for some reason an error occurs when trying to access the data file. Example: Type InfoType : Word; {A file of unsigned integers!} Procedure DoSomething; Var MyFile : TFreadPtr; {a pointer to the TFread object} Info : InfoType; i : integer; Begin New(MyFile,Init('TEST.DAT',OpenCreate,SizeOf(InfoType))); MyFile^.ReadRec(Info,MyFile^.NumRecs); {Start at last record!} {Read and display backwards the 100 words randomly created. } while not MyFile^.ReadError do begin writeln(Info); Myfile^.ReadPrevious(Info); end; Dispose(MyFile,Done); End; ---------------------------------------------------------------------------- Procedure ReadCurrent(var frec); TFread keeps track of the current record (the last record that had been read). Using ReadCurrent will read the record at the Current location and return it in Frec. The same conditions apply for ther ReadError flag as they do in the previous file read methods. Example: Type InfoType : Word; {A file of unsigned integers!} Procedure DoSomething; Var MyFile : TFreadPtr; {a pointer to the TFread object} Info : InfoType; Begin New(MyFile,Init('TEST.DAT',OpenCreate,SizeOf(InfoType))); . . . MyFile^.ReadCurrent(Info); {Reads the current record into Info} Dispose(MyFile,Done); End; ---------------------------------------------------------------------------- Procedure EraseFile; Erasefile will close the file then erase it from the disk. Like the Done destructor, once this procedure is called, then none of the file accessing methods can be used because there will be no more file to use them with. Example: Procedure DoSomething; Var MyFile : TFreadPtr; {a pointer to the TFread object} Begin New(MyFile,Init('TEST.DAT',OpenCreate,SizeOf(InfoType))); . . . MyFile^.EraseFile; {Erases the current file} Dispose(MyFile,Done); End; ---------------------------------------------------------------------------- Function RenameFile(fn:string):boolean; RenameFile will rename the file to the specified string passed in as fn. If the file could not be renamed (i.e. you are attempting to rename a file to another file that already exists) then the function will return false. Renaming the file will in no way alter anything within the object. This function will just rename the physical file on disk, leaving you where you last left off. Example: Type InfoType : Word; {A file of unsigned integers!} Procedure DoSomething; Var MyFile : TFreadPtr; {a pointer to the TFread object} Info : InfoType; Success : Boolean; Begin New(MyFile,Init('TEST.DAT',OpenCreate,SizeOf(InfoType))); . . . MyFile^.ReadCurrent(Info); {Reads the current record into Info} Success:=MyFile^.RenameFile('SOMETHING.DAT'); {could we rename the file?} if Success then MyFile^.ReadCurrent(Info); {Still at same position} Dispose(MyFile,Done); End; ---------------------------------------------------------------------------- Procedure Rewind; Rewind will reset the file pointer and the Current position to the beginning of the file. Example: Type InfoType : Word; {A file of unsigned integers!} Procedure DoSomething; Var MyFile : TFreadPtr; {a pointer to the TFread object} Info : InfoType; i : integer; Begin New(MyFile,Init('TEST.DAT',OpenCreate,SizeOf(InfoType))); for i:=1 to 10 do begin MyFile^.ReadRec(Info,i-1); Writeln(Info); end; {Now at the tenth record.} MyFile^.Rewind; {Now at the first record!} . . . Dispose(MyFile,Done); End; ---------------------------------------------------------------------------- Function NumRecs : Longint; Numrecs will return the number of physical elements within the file. For instance, if you create a file of type integer and write 100 integers to disk, NumRecs will return 100. The same applies for records, or arrays, or whatever you wish to create a file of. Example: Type InfoType : Word; {A file of unsigned integers!} Procedure DoSomething; Var MyFile : TFreadPtr; {a pointer to the TFread object} Info : InfoType; Begin New(MyFile,Init('TEST.DAT',OpenCreate,SizeOf(InfoType))); Writeln('Number of records in file: ',MyFile^.NumRecs); . . . Dispose(MyFile,Done); End; ---------------------------------------------------------------------------- Function GetFilename : String; GetFilename will return the actual name of the file as it appears on the disk. Example: Type InfoType : Word; {A file of unsigned integers!} Procedure DoSomething; Var MyFile : TFreadPtr; {a pointer to the TFread object} Info : InfoType; Begin New(MyFile,Init('TEST.DAT',OpenCreate,SizeOf(InfoType))); Writeln('The name of the file is ',MyFile^.GetFilename); . . . Dispose(MyFile,Done); End; ---------------------------------------------------------------------------- Function GetCurrent : Longint; GetCurrent will return the physical record number where the object TFread is currently pointing. Example: Type InfoType : Word; {A file of unsigned integers!} Procedure DoSomething; Var MyFile : TFreadPtr; {a pointer to the TFread object} Info : InfoType; i : integer; Begin New(MyFile,Init('TEST.DAT',OpenCreate,SizeOf(InfoType))); {reads in the first 10 random numbers in the file and displays the physical record number and the generated random number} for i:=1 to 10 do begin MyFile^.ReadRec(Info,i-1); Writeln(MyFile^.GetCurrent:4,' ',Info); end; Dispose(MyFile,Done); End; ---------------------------------------------------------------------------- Function OpenError : boolean; OpenError will return the status of the OpenError flag. This flag is set true if the file has been successfully opened or created. Otherwise OpenError will be set to false. Example: Type InfoType : Word; {A file of unsigned integers!} Procedure DoSomething; Var MyFile : TFreadPtr; {a pointer to the TFread object} Info : InfoType; i : integer; Begin New(MyFile,Init('TEST.DAT',OpenCreate,SizeOf(InfoType))); if MyFile^.OpenError then writeln('Error openning file, aborting!') else . . . End; ---------------------------------------------------------------------------- Function ReadError : boolean; ReadError will be set true if any of the read methods have successfully read a record. Otherwise this function will return a false. Example: Type InfoType : Word; {A file of unsigned integers!} Procedure DoSomething; Var MyFile : TFreadPtr; {a pointer to the TFread object} Info : InfoType; i : integer; Begin New(MyFile,Init('TEST.DAT',OpenCreate,SizeOf(InfoType))); if MyFile^.OpenError then writeln('Error openning file, aborting!') else begin MyFile^.ReadRec(Info,101); {attempt to read record 101!} if MyFile^.ReadError then writeln('Could not read that record!'); . . . end; End; ---------------------------------------------------------------------------- Function WriteError : boolean; WriteError will be set to true if any of the file write methods have successfully writen the data to disk. Otherwise this function will return false. Example: Type InfoType : Word; {A file of unsigned integers!} Procedure DoSomething; Var MyFile : TFreadPtr; {a pointer to the TFread object} Info : InfoType; i : integer; Begin New(MyFile,Init('TEST.DAT',OpenCreate,SizeOf(InfoType))); if MyFile^.OpenError then writeln('Error openning file, aborting!') else begin MyFile^.WriteRec(Info,200); {attempt to update record 200!} if MyFile^.WriteError then writeln('Could not update that record!'); . . . end; End; ---------------------------------------------------------------------------- Function Exist(fn:string) : Boolean; There is also a useful function in the interface section called Exist which will return True if the file specified in the Fn string variable exists. This is used by the object but can also be used as a stand alone procedure. Example: If not Exist('TEST.DAT') then writeln('Error: Could not locate file!') else . . . ---------------------------------------------------------------------------- ENDING NOTES This is merely the first version of this software library, and no attempts to include internal buffering have been attempted. I am planning with future releases to have some kind of internal buffering that might make the file accessing faster. Since this is an object, however, you could take it upon yourself to write your own object which would inherit mine and add your own buffering handler. Shareware, as you already may know, is an important part of today's computing world. I implore you, if you use shareware and don't register, please do so. Many authors out there would greatly appreciate the donation and the incentive may be enough to encourage the author to produce an even more robust version of his or her software. My address and telephone number follows as does the numbers of a few bulletin boards where I can be reached: Thomas J. Clancy Jr. 5861 Horseshoe Drive Bethel Park, PA 15102 Home Phone: (412) 833-7754 BBS's: The Titusville Connection : (814) 827-1234 Century Products BBS : (412) 831-5438 Technicomm BBS : (412) 885-4347 Thiel College BBS : (412) 589-2039 SV Educational BBS : (412) 962-0765