Сканируем файл в поисках текста

Советы » Файлы » Сканируем файл в поисках текста

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 }

Другое по теме:

Категории

Статьи

Советы

Copyright © 2022 - All Rights Reserved - www.delphirus.com