home *** CD-ROM | disk | FTP | other *** search
/ Programmer 7500 / MAX_PROGRAMMERS.iso / INFO / TURBOPAS / MISC.ZIP / TXTSEEK.PAS < prev   
Encoding:
Pascal/Delphi Source File  |  1985-12-04  |  6.6 KB  |  235 lines

  1. PROGRAM textseek;
  2.  
  3.   {
  4.   Demonstrate a technique for making a normal text file into a fully indexed
  5.   file, where any line can be read randomly by line number. Each line must
  6.   be terminated by at least a <LF>.
  7.  
  8.   Useful for text sort programs, large file editors, text databases, etc.
  9.  
  10.   Should run on any PCDOS or MSDOS Turbo 3.0 (developed on IBM).
  11.  
  12.   Written 10/5/85, Kim Kokkonen, TurboPower Software.
  13.   408-378-3672, CompuServe 72457,2131.
  14.  
  15.   Released to the public domain.
  16.   }
  17.  
  18. CONST
  19.   {maxlines*maxlength gives the maximum filesize, here about 2.3 megabytes}
  20.   MaxLines = 9000;            {limited by 7*maxlines<=65536}
  21.   MaxLength = 255;            {max length of a given line, limited to 255}
  22.   BufSize = 4096;             {number of bytes per blockread}
  23.  
  24. TYPE
  25.   TextString = STRING[MaxLength];
  26.   PathName = STRING[64];
  27.   FilePointer = RECORD
  28.                   SeekTo : Real;
  29.                   LenToRead : Byte;
  30.                 END;
  31.   FileIndexArray = ARRAY[1..MaxLines] OF FilePointer;
  32.   FileIndexPtr = ^FileIndexArray;
  33.   TextBuffer = ARRAY[1..BufSize] OF Char;
  34.   TextBufferPtr = ^TextBuffer;
  35.  
  36.   {following record carries all information about the indexed text file}
  37.   {requires 97 bytes in the segment where its var is located}
  38.   {requires 7*maxlines+bufsize on the heap}
  39.   IndexedFile =
  40.   RECORD
  41.     fil : FILE;               {untyped file is critical for this application}
  42.     EndOfFile : Boolean;      {true when all of file read}
  43.     LineNum : Integer;        {last line read in}
  44.     FilePosition : Real;      {current byte position in file during readin}
  45.     Buffer : TextBufferPtr;   {pointer to buffer for this file}
  46.     BufPos : Integer;         {position in current buffer}
  47.     BytesRead : Integer;      {number read in last blockread}
  48.     index : FileIndexPtr;     {pointer to file index}
  49.   END;
  50.  
  51. VAR
  52.   fname : PathName;
  53.   F : IndexedFile;
  54.   L : TextString;
  55.   LineToSeek : Integer;
  56.   Success : Boolean;
  57.  
  58.   FUNCTION Cardinal(i : Integer) : Real;
  59.     {-return positive real 0<=r<=65535}
  60.   VAR
  61.     r : Real;
  62.   BEGIN
  63.     r := i;
  64.     IF r < 0 THEN r := r+65536.0;
  65.     Cardinal := r;
  66.   END;                        {cardinal}
  67.  
  68.   PROCEDURE OpenFile(fname : PathName;
  69.                      VAR F : IndexedFile;
  70.                      VAR Success : Boolean);
  71.     {-open an indexed textfile, return true if successful}
  72.   BEGIN
  73.     WITH F DO BEGIN
  74.  
  75.       {open the physical file}
  76.       Assign(fil, fname);
  77.       {$I-} Reset(fil, 1) {$I+} ;
  78.       Success := (IOResult = 0);
  79.       IF NOT(Success) THEN Exit;
  80.       EndOfFile := False;
  81.  
  82.       {allocate the file buffer}
  83.       Success := 16.0*Cardinal(MaxAvail) > Cardinal(SizeOf(TextBuffer));
  84.       IF NOT(Success) THEN BEGIN
  85.         Close(fil);
  86.         Exit;
  87.       END;
  88.       New(Buffer);
  89.       BytesRead := 0;
  90.       BufPos := 1;            {force blockread the first time}
  91.  
  92.       {allocate the lines array}
  93.       Success := 16.0*Cardinal(MaxAvail) > Cardinal(SizeOf(FileIndexArray));
  94.       IF NOT(Success) THEN BEGIN
  95.         Close(fil);
  96.         Exit;
  97.       END;
  98.       New(index);
  99.       LineNum := 0;
  100.       FilePosition := 0.0;
  101.  
  102.     END;
  103.   END;                        {openfile}
  104.  
  105.   PROCEDURE CloseFile(VAR F : IndexedFile);
  106.     {-free up dynamic space and close physical file}
  107.   BEGIN
  108.     WITH F DO BEGIN
  109.       Close(fil);
  110.       Dispose(index);
  111.       Dispose(Buffer);
  112.     END;
  113.   END;                        {closefile}
  114.  
  115.   PROCEDURE ReadNewLine(VAR F : IndexedFile; VAR L : TextString);
  116.     {-read a text line and store information for later random access}
  117.   VAR
  118.     EndOfLine : Boolean;
  119.     lpos, terminators : Integer;
  120.     ch : Char;
  121.   BEGIN
  122.     WITH F DO BEGIN
  123.       EndOfLine := False;
  124.       lpos := 0;
  125.       terminators := 1;
  126.  
  127.       {look at characters until end of line found}
  128.       REPEAT
  129.  
  130.         IF BufPos > BytesRead THEN BEGIN
  131.           {get another buffer full}
  132.           BlockRead(fil, Buffer^, BufSize, BytesRead);
  133.           BufPos := 1;
  134.         END;
  135.  
  136.         IF BytesRead = 0 THEN
  137.           ch := ^Z
  138.         ELSE BEGIN
  139.           ch := Buffer^[BufPos];
  140.           BufPos := Succ(BufPos);
  141.         END;
  142.  
  143.         CASE ch OF
  144.           ^M : terminators := Succ(terminators);
  145.           ^J : EndOfLine := True;
  146.           ^Z : BEGIN
  147.                  EndOfLine := True;
  148.                  EndOfFile := True;
  149.                END;
  150.         ELSE
  151.           IF lpos < MaxLength THEN BEGIN
  152.             lpos := Succ(lpos);
  153.             L[lpos] := ch;
  154.           END;
  155.         END;
  156.  
  157.       UNTIL EndOfLine;
  158.  
  159.       {finish up line}
  160.       L[0] := Chr(lpos);
  161.  
  162.       {store info for later random access}
  163.       IF LineNum < MaxLines THEN BEGIN
  164.         LineNum := Succ(LineNum);
  165.         WITH index^[LineNum] DO BEGIN
  166.           SeekTo := FilePosition;
  167.           LenToRead := lpos;
  168.         END;
  169.         FilePosition := FilePosition+lpos+terminators;
  170.       END;
  171.  
  172.     END;
  173.   END;                        {readnewline}
  174.  
  175.   PROCEDURE ReadIndexedLine(VAR F : IndexedFile;
  176.                             VAR Num : Integer;
  177.                             VAR L : TextString);
  178.     {-get an indexed line from f}
  179.     {increment num for quasi-sequential access}
  180.   BEGIN
  181.     WITH F DO BEGIN
  182.       IF (Num > 0) AND (Num < LineNum) THEN BEGIN
  183.         WITH index^[Num] DO BEGIN
  184.           LongSeek(fil, SeekTo);
  185.           BlockRead(fil, L[1], LenToRead);
  186.           L[0] := Chr(LenToRead);
  187.         END;
  188.         Num := Succ(Num);
  189.       END ELSE BEGIN
  190.         L := '';
  191.         Num := 0;
  192.       END;
  193.     END;
  194.   END;                        {readindexedline}
  195.  
  196.   PROCEDURE BuildFileIndex(fname : PathName;
  197.                            VAR F : IndexedFile;
  198.                            VAR Success : Boolean);
  199.     {-read a text file and define index pointers for random access}
  200.   VAR
  201.     L : TextString;
  202.   BEGIN
  203.     OpenFile(fname, F, Success);
  204.     IF NOT(Success) THEN Exit;
  205.     {read it all to get the filepointers}
  206.     {ignore the returned string l in this case}
  207.     WHILE NOT(F.EndOfFile) DO ReadNewLine(F, L);
  208.   END;                        {buildfilepointers}
  209.  
  210. BEGIN
  211.  
  212.   {get a file to read, and read it in}
  213.   Write('Enter text file name to read: ');
  214.   ReadLn(fname);
  215.   WriteLn('Reading');
  216.   BuildFileIndex(fname, F, Success);
  217.   IF NOT(Success) THEN BEGIN
  218.     WriteLn('could not build index...');
  219.     Halt;
  220.   END;
  221.  
  222.   {demonstrate random access}
  223.   REPEAT
  224.     Write('Enter any linenumber (0 to quit, max ', F.LineNum, '): ');
  225.     ReadLn(LineToSeek);
  226.     IF LineToSeek > 0 THEN BEGIN
  227.       ReadIndexedLine(F, LineToSeek, L);
  228.       WriteLn(L);
  229.     END;
  230.   UNTIL LineToSeek = 0;
  231.  
  232.   CloseFile(F);
  233.  
  234. END.
  235.