From: "Peter Below (TeamB)" <100113.1101@compuXXserve.com> Subject: Re: File TextSearch Date: 16 Jul 1999 00:00:00 GMT Message-ID: Content-Transfer-Encoding: 8bit References: <7mmuee$76r8@forums.borland.com> Content-Type: text/plain; charset=iso-8859-1 Organization: TeamB Mime-Version: 1.0 Reply-To: 100113.1101@compuXXserve.com Newsgroups: borland.public.delphi.objectpascal In article <7mmuee$76r8@forums.borland.com>, Jure wrote: > Can anyone tell how to search file for a specified text > (like windows Find command does) with the fastest (or > not very slow) method ? > Function ScanFile( Const filename: String; Const forString: String; caseSensitive: Boolean ): LongInt; { returns position of string in file or -1, if not found } Const BufferSize= $8001; { 32K+1 bytes } Var pBuf, pEnd, pScan, pPos : Pchar; filesize: LongInt; bytesRemaining: LongInt; bytesToRead: Word; F : File; SearchFor: Pchar; oldMode: Word; Begin Result := -1; { assume failure } If (Length( forString ) = 0) or (Length( filename ) = 0) Then Exit; SearchFor := Nil; pBuf := Nil; { open file as binary, 1 byte recordsize } AssignFile( F, filename ); oldMode := FileMode; FileMode := 0; { read-only access } Reset( F, 1 ); FileMode := oldMode; try { allocate memory for buffer and pchar search string } SearchFor := StrAlloc( Length( forString )+1 ); StrPCopy( SearchFor, forString ); If not caseSensitive Then { convert to upper case } AnsiUpper( SearchFor ); GetMem( pBuf, BufferSize ); filesize := System.Filesize( F ); bytesRemaining := filesize; pPos := Nil; While bytesRemaining > 0 Do Begin { calc how many bytes to read this round } If bytesRemaining >= BufferSize Then bytesToRead := Pred( BufferSize ) Else bytesToRead := bytesRemaining; { read a buffer full and zero-terminate the buffer } BlockRead( F, pBuf^, bytesToRead, bytesToRead ); pEnd := @pBuf[ bytesToRead ]; pEnd^:= #0; { scan the buffer. Problem: buffer may contain #0 chars! So we treat it as a concatenation of zero-terminated strings. } pScan := pBuf; While pScan < pEnd Do Begin If not caseSensitive Then { convert to upper case } AnsiUpper( pScan ); pPos := StrPos( pScan, SearchFor ); { search for substring } If pPos <> Nil Then Begin { Found it! } Result := FileSize - bytesRemaining + LongInt( pPos ) - LongInt( pBuf ); Break; End; pScan := StrEnd( pScan ); Inc( pScan ); End; If pPos <> Nil Then Break; bytesRemaining := bytesRemaining - bytesToRead; If bytesRemaining > 0 Then Begin { no luck in this buffers load. We need to handle the case of the search string spanning two chunks of file now. We simply go back a bit in the file and read from there, thus inspecting some characters twice } Seek( F, FilePos(F)-Length( forString )); bytesRemaining := bytesRemaining + Length( forString ); End; End; { While } finally CloseFile( F ); If SearchFor <> Nil Then StrDispose( SearchFor ); If pBuf <> Nil Then FreeMem( pBuf, BufferSize ); end; end; { ScanFile } Peter Below (TeamB) 100113.1101@compuserve.com) No e-mail responses, please, unless explicitly requested!