Карта сайта Kansoftware
НОВОСТИУСЛУГИРЕШЕНИЯКОНТАКТЫ
KANSoftWare

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

Delphi , Файловая система , Файлы

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


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 }

Перевод контента на русский язык:

Функция Delphi ScanFile сканирует файл для указанной строки и возвращает позицию первого вхождения строки в файле. Если строка не найдена, функция возвращает -1.

Распределение работы функции:

  1. Функция принимает три параметра: FileName, forString и caseSensitive. FileName - имя файла для сканирования, forString - строка для поиска, а caseSensitive - булевое значение, указывающее, является ли поиск чувствительным к регистру или нет.
  2. Функция проверяет, не пусты ли FileName или forString. Если это так, функция возвращает сразу без выполнения дальнейших операций.
  3. Затем функция открывает файл, указанный в FileName, в бинарном режиме и сбрасывает его позицию к началу файла.
  4. Функция выделяет память для буфера (называемого pBuf) и строки поиска (называемой SearchFor). Размер буфера установлен в 32K+1 байт, что является разумным размером для большинства файлов.
  5. Функция затем вступает в цикл, который читает файл блоками до 32K байт в каждом. Для каждого блока функция ищет указанную строку с помощью функции StrPos и обновляет свою позицию соответственно.
  6. Если строка найдена, функция возвращает позицию первого вхождения строки в файле.
  7. Если цикл завершается без нахождения строки, функция возвращает -1.

Некоторые потенциальные проблемы с этим кодом:

  • Поиск строки может быть неэффективным, если файл содержит много вхождений одной и той же строки, поскольку функция будет продолжать поиск откуда она оставила, даже после обнаружения совпадения.
  • Код предполагает, что файл мал, чтобы поместиться в память. Если файл очень большой, это может вызвать проблемы с памятью.

Альтернативное решение могло бы быть использованием подхода потокового чтения, где функция читает файл по одному байту за раз и ищет строку на ходу. Это бы устранило необходимость в буферах и уменьшило потребление памяти. Однако, это подход может быть медленнее, чем текущая реализация.

Пример того, как функция могла быть переписана с использованием потокового подхода:

function ScanFile(FileName: string; forString: string; caseSensitive: Boolean): Longint;
var
  F: file;
  SearchFor: PChar;
  pPos: PChar;
begin
  Result := -1;
  if Length(forString) = 0 or Length(FileName) = 0 then Exit;

  AssignFile(F, FileName);
  Reset(F);

  SearchFor := nil;
  pPos := nil;

  try
    while not Eof(F) do
    begin
      BlockRead(F, pPos^, 1, 1);
      if not caseSensitive then AnsiUpper(pPos);

      if StrPos(pPos, forString) <> nil then
      begin
        Result := FileSeek(F, 0) + Length(forString) - Length(pPos);
        Break;
      end;

      Inc(FileSeek(F), 1);
    end;

  finally
    CloseFile(F);
  end;
end;

Эта реализация может быть более память-эффективной, чем оригинальный код, но может быть медленнее из-за дополнительного чтения по одному байту за раз.

Сканируем файл в поисках текста: функция ScanFile позволяет найти положение указанного текстового fragments в файле.


Комментарии и вопросы

Получайте свежие новости и обновления по Object Pascal, Delphi и Lazarus прямо в свой смартфон. Подпишитесь на наш Telegram-канал delphi_kansoftware и будьте в курсе последних тенденций в разработке под Linux, Windows, Android и iOS




Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта.


:: Главная :: Файлы ::


реклама


©KANSoftWare (разработка программного обеспечения, создание программ, создание интерактивных сайтов), 2007
Top.Mail.Ru

Время компиляции файла: 2024-08-19 13:29:56
2024-10-24 20:02:55/0.0039219856262207/0