[Back to FILES SWAG index] [Back to Main SWAG index] [Original]

    {*************************************************************************
     *                    LOW LEVEL FILE READING OBJECT                      *
     *                                                                       *
     *                      Copyright 1992 Tom Clancy                        *
     *                                                                       *
     *   Description:                                                        *
     *                                                                       *
     *        This library allows you to create a file of any type record    *
     *   by passing in the record size.  You must also pass in a record of   *
     *   the same type that the object has been initialized with so that     *
     *   you don't get errors when reading and writing.                      *
     *                                                                       *
     *        There is no internal buffering, but the routines are fairly    *
     *   fast and because each file is actually an object, you can create    *
     *   higher level objects of this object type that allow more            *
     *   flexibility, such as indexing and sorting.                          *
     *                                                                       *
     *************************************************************************}

    {$I-}   {Turn off I/O checking}
    {$S-}   {Turn off Stack checking}
    {$R-}   {Turn off Range checking}
    {$V-}   {No strict VAR string checking allowed here!}

    Unit FileRead;

    Interface

    Const

       Open       = 1;
       Create     = 2;
       OpenCreate = 3;

    Type

       TFreadPtr = ^TFreadObj;
       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;

       private
         Ifile       : File;     {file variable}
         Rsize       : Longint;  {the internal record size}
         FileName    : String;   {physical file name}
         Oerror,                 {open error flag}
         Rerror,                 {read error flag}
         Werror      : Boolean;  {write error flag}
         Current     : Longint;  {current file pointer location}

         { methods used internally.  No access allowed! }
         Procedure   OpenFile;
         Procedure   CreateFile;
         Procedure   CloseFile;
       end;

    Function Exist(fn:string):Boolean;

    Implementation

    uses
      Dos;

    { Pass in a string which contains a file name to see if that file exists.}
    Function Exist(fn:string):Boolean;
    Var
       DirInfo : SearchRec;
    Begin
      FindFirst(fn,Archive,DirInfo);
      Exist:=DosError=0;
    End;

    {
        Initialize the object.

        Fn    = File name
        Mode  = Open, Create, or OpenCreate
          - Open will try to open the file.  An error is set if the file does not
            exist.
          - Create will create the file regardless if it's there or not.
          - OpenCreate will attemp to open the file first, then create it if it's
            not there.
        RecSize = The size of the records that the file will contain.
          - Use Sizeof(Rec) for safety.
    }
    Constructor TFreadObj.Init(fn:string; mode:integer; recsize:longint);
    Begin
      Oerror:=true;
      Rerror:=false;
      Werror:=false;
      Rsize:=recsize;
      FileName := fn;
      Assign(Ifile,FileName);
      case mode of
        Open       : openfile;
        Create     : createfile;
        OpenCreate :
          begin
            OpenFile;
            if Oerror then
              CreateFile;
          end;
      end;
    End;

    { Close the file when disposing object. }
    Destructor TFreadObj.done;
    begin
      CloseFile;
    end;

    { Open the file.  Set an error if it could not open. }
    Procedure TFreadObj.OpenFile;
    Begin
      if Exist(FileName) then
      begin
        Oerror:=false;
        Reset(Ifile,Rsize);
        Current:=0;
      end
      else
        Oerror:=true;
    End;

    { Create a new file, zeroing out an existing file.}
    Procedure TFreadObj.CreateFile;
    Begin
      Rewrite(Ifile,Rsize);
      Current:=0;
      Oerror:=Ioresult<>0;
    end;

    { Close the file only if it has been successfully opened.}
    Procedure TFreadObj.CloseFile;
    Begin
      if not Oerror then
      begin
        Close(Ifile);
        Oerror:=true;
      end;
    End;

    { Will erase the file.}
    Procedure TFreadObj.EraseFile;
    Begin
      if not Oerror then
      begin
        CloseFile;
        Erase(Ifile);
      end;
    End;

    { Renames the file.}
    Function TFreadObj.RenameFile(fn:string):Boolean;
    Var
      Temp : Longint; {Save the current file pointer}
    Begin
      CloseFile;
      FileName:=fn;
      Rename(Ifile,FileName);
      if ioresult=0 then
      begin
        Temp:=Current;
        Assign(Ifile,FileName);
        OpenFile;
        Current:=Temp;
      end;
      RenameFile := not Oerror;
    end;

    { Rewinds the file pointer back to the beginning.}
    Procedure TFreadObj.Rewind;
    Begin
      if not Oerror then
      begin
        Seek(Ifile,0);
        Current:=0;
      end;
    end;

    Function TFreadObj.OpenError:Boolean;
    Begin
      OpenError:=Oerror;
    End;

    Function TFreadObj.ReadError:Boolean;
    Begin
      ReadError:=Rerror;
    End;

    Function TFreadObj.WriteError:Boolean;
    Begin
      WriteError:=Werror;
    End;

    { Reads a record from the file at location FPOS.  Returns the record in
      Frec.}
    Procedure TFreadObj.ReadRec(var frec; fpos:longint);
    Var
      numread : word;
    Begin
      Rerror:=false;
      if not Oerror then
      begin
        Seek(Ifile,fpos);
        if ioresult<>0 then
          Rerror:=true
        else
        begin
          Blockread(Ifile,frec,1,numread);
          if (numread<>1) or (ioresult<>0) then
            Rerror:=true
          else
            Current:=fpos;
        end;
      end;
    End;

    { Writes a record to the file at location Fpos.}
    Procedure TFreadObj.WriteRec(var frec; fpos:longint);
    Var
      numwritten : word;
      i:integer;
    Begin
      Werror:=false;
      if not Oerror then
      begin
        Seek(Ifile,fpos);
        if Ioresult<>0 then
          Werror:=true
        else
        begin
          Blockwrite(Ifile,frec,1,numwritten);
          if (numwritten<>1) or (ioresult<>0) then
            Werror:=true
          else
            Current:=fpos;
        end;
      end;
    End;

    { Appends a record to the end of the file.}
    Procedure TFreadObj.AppendRec(var frec);
    Begin
      WriteRec(frec,NumRecs);
    End;

    { Reads the next record from the file, allowing sequential access.}
    Procedure TFreadObj.ReadNext(var frec);
    Begin
      ReadRec(frec,Current+1);
    End;

    { Reads the previous record from the file. }
    Procedure TFreadObj.ReadPrevious(var frec);
    Begin
      ReadRec(frec,Current-1);
    End;

    { Reads the record pointed to by current. }
    Procedure TFreadObj.ReadCurrent(var frec);
    Begin
      ReadRec(frec,Current);
    End;

    { Returns the number of records in the file.}
    Function TFreadObj.NumRecs:Longint;
    Begin
      if not Oerror then
        NumRecs:=Filesize(Ifile);
    End;

    { Returns the file name of the file.}
    Function TFreadObj.GetFilename : String;
    Begin
      GetFilename:=FileName;
    End;

    { Returns the number of the current record. }
    Function TFreadObj.GetCurrent : Longint;
    Begin
      GetCurrent:=Current;
    End;

    { No initialization required.}
    end.

[Back to FILES SWAG index] [Back to Main SWAG index] [Original]