| 
 
 
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 }
 
 
 
   |