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

    {
    > Unfortunately this won't work, for some reason BP ignores the FileMode
    > variable when dealing with a file of type Text.  I modified one of the
    > RTL files to correct this problem

       This is not directed specifically to you, but to anyone that's interested in
    a unit that can read big textfiles (like loggfiles, nodelists and so on) in a
    fast way. It can only handle one file at a time and with later versions of TP/
    BP the speed increase isn't as dramatic as it was in older versions, that
    hadn't stuff like buffered textfiles. I use it a lot (even in network
    environments -- with FileMode set to $40).
    }

    unit FileUtil; { unit for fast reading of large textfiles }

    { Donated to the PD by Bj�rn Felten @ 2:203/208 -- Nov 1994 }
    { From the package BF_UTIL.ZIP }

    interface

    var
        Line    :string; { where the read line is returned }
                         { a global is used for higher speed }
        XEof    :boolean;

    procedure XReset;
    procedure XReadLn(var FileHandle: file);
    procedure XOpen(var FileHandle: file; FileName: string);
    procedure XClose(var FileHandle: file);

    implementation

    const
        BufSiz = $e000;

    type
        Buffer = array[1..BufSiz+2] of char;
        BufPtr = ^Buffer;

    var
        TempLine    :string;
        Buff        :BufPtr;
        Segm,Offs,
        NumRead,
        LastPos,
        FirstPos    : Word;

    procedure XReset;
    begin
       FirstPos:=0;
       LastPos:=FirstPos;
       XEof:=false
    end
    ;

    procedure XReadLn(var FileHandle: file);
    begin
        asm
          mov  es,Segm      { just to be sure }
          mov  bx,es
          mov  dx,ds
          cld
          mov  di,LastPos   { start within file }
          add  di,Offs
          mov  al,13        { set up a search for CR }
          mov  cx,257       { max 255 char plus overhead }
          mov  si,di
          repnz scasb       { look for CR }
          mov  di,offset Line   { put it into string }
          neg  cl           { get string length }
          mov  [di],cl      { put it in first position }
          je   @empty
          inc  di
          mov  ds,bx        { swap es and ds}
          mov  es,dx
          rep  movsb        { move it }
    @empty:
          lodsw             { skip CR/LF }
          mov  ds,dx        { restore ds }
          sub  si,Offs
          mov  LastPos,si   { save last position }
     end
     ;
     if LastPos>=BufSiz then
     begin
       TempLine:=Line; { handle partial line at block boundary }
       blockread(FileHandle,Buff^,BufSiz,NumRead);
       XReset;
       XReadLn(FileHandle);
       Line:=TempLine+Line
     end
     ;
     XEof:=(LastPos>=NumRead)
    end;

    procedure XOpen(var FileHandle: file; FileName: string);
    begin
      assign(FileHandle,FileName);
      (*$I-*) reset(FileHandle,1) (*$I+*)
      ;
      if IoResult<>0 then
      begin
         writeln;
         writeln('Can''t find ',FileName,' in this directory!');
         writeln;
         halt(2)
      end
      ;
      if memavail<BufSiz+$400 then
      begin
         writeln;
         writeln('Need at least ',BufSiz shr 10,'kb RAM!');
         writeln;
         halt(3)
      end
      ;
      new(Buff);
      Segm:=seg(Buff^);
      Offs:=ofs(Buff^);
      Buff^[BufSiz+1]:=#13;  { stuff some CR's in to avoid running }
      Buff^[BufSiz+2]:=#13;  { off limits if unlucky w/ boundaries }
      blockread(FileHandle,Buff^,BufSiz,NumRead);
      Buff^[NumRead+1]:=#13;
      Buff^[NumRead+2]:=#13;
      XReset
    end
    ;
    procedure XClose(var FileHandle: file);
    begin
       close(FileHandle);
       dispose(Buff)
    end
    ;

    end.

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