Finding word in file

I want to search for a word in any readable file (.txt, .php, etc) in a folder and all sub-folders.  When any are found (there may be several), the name of the file and also the line number will be added to a memo.

I am using Delphi 6.  Many thanks for your help.
rincewind666Asked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

Geert GOracle dbaCommented:
don't you think your scope is a little broad for a project ?

numerous topics on finding files in folders:
http://www.experts-exchange.com/Programming/Languages/Pascal/Delphi/Q_21195960.html
http://www.experts-exchange.com/Programming/Languages/Pascal/Delphi/Q_21388532.html

Finding a word : Use Regular expresions to find a word (surrounded by word boundaries):
http://regexpstudio.com/TRegExpr/Help/About.html
Use the following function to find any word in a file and separate it into a stringlist

 
uses RegExpr;

procedure GetWordsInFile(aFileName: string: aWordList: TStrings);
var List: TStringList;
begin
  List := TStringList.Create;
  try
    List.LoadFromFile(aFileName);
    SplitRegExpr('\b\w+\b', aWordList);
  finally 
    List.Free;
  end;
end;

Open in new window


off course you'll have to deal with large files
> split them into chunks when reading

what do you want to do with the results ?
> memory will be too small

0
Geert GOracle dbaCommented:
oops, typo:

SplitRegExpr('\b\w+\b', List.Text, aWordList);
0
Emmanuel PASQUIERFreelance Project ManagerCommented:
first, you have to list all files you want to scan.

Here is a tool function to list files matching some mask. It is very versatile, for many such usages (it can even get some basic file information if you add soDates option)
Unit untFindFiles;

Interface

Uses Classes,SysUtils,Windows;

Type
 TSearchOption=(soRecurse,soFullName,soClearList,soResIncludeDir,soDates);
 TSearchOptions=Set of TSearchOption; 
 TFileDates=class(TObject)
 public
  CreateDT, AccessDT, ModifyDT: TDateTime;
  Size:Cardinal;
 end;

procedure FindFiles(Dir,Search:String;Res:TStrings;OrAttr:Integer=faAnyFile;AndAttr:Integer=0;Options:TSearchOptions=[];SubDir:STring='';FixedSubDir:String='';Level:integer=0);
function FileTimeToDTime(FTime: TFileTime): TDateTime;

implementation

function FileTimeToDTime(FTime: TFileTime): TDateTime;
var
  LocalFTime: TFileTime;
  STime: TSystemTime;
begin
  FileTimeToLocalFileTime(FTime, LocalFTime);
  FileTimeToSystemTime(LocalFTime, STime);
  Result := SystemTimeToDateTime(STime);
end;

procedure FindFiles(Dir,Search:String;Res:TStrings;OrAttr:Integer=faAnyFile;AndAttr:Integer=0;Options:TSearchOptions=[];SubDir:STring='';FixedSubDir:String='';Level:integer=0);
Var
 R:TSearchRec;
 S:String;
 R2:TStringList;
 FileDates:TFileDates;
 i:integer;
begin
 Dir:=IncludeTrailingBackslash(Dir);
 OrAttr:=OrAttr Or AndAttr;
 if SubDir<>'' Then SubDir:=IncludeTrailingBackSlash(SubDir);
 if FixedSubDir<>'' Then FixedSubDir:=IncludeTrailingBackSlash(FixedSubDir);
 if soClearList IN Options Then
  begin
   for i:=0 to Res.Count-1 do try Res.Objects[i].Free except end;
   Res.Clear;
   Options:=Options-[soClearList];
  end;
 if soRecurse IN Options Then OrAttr:=OrAttr Or faDirectory;
 if FindFirst(Dir+SubDir+FixedSubDir+Search,OrAttr,R)=0 then
  repeat
   if (R.Attr And AndAttr)=AndAttr Then
    begin
     S:=SubDir+FixedSubDir+R.Name;
     if soFullName IN Options Then Res.Add(Dir+S) Else Res.Add(S);
     if soDates IN Options Then
      begin
       FileDates:=TFileDates.Create;
       With FileDates do
        begin
         CreateDT := FileTimeToDTime(R.FindData.ftCreationTime);
         AccessDT := FileTimeToDTime(R.FindData.ftLastAccessTime);;
         ModifyDT := FileTimeToDTime(R.FindData.ftLastWriteTime);;
         Size:=R.Size;
        end;
       Res.Objects[Res.Count-1]:=FileDates;
      end;
    end;
  until FindNext(R)<>0;
 if (soRecurse IN Options) And (FindFirst(Dir+SubDir+FixedSubDir+'*.*',faDirectory,R)=0) then
  repeat
   if ((R.Attr And faDirectory)>0) And (R.Name[1]<>'.') Then
    begin
     R2:=TStringList.Create;
     FindFiles(Dir,Search,R2,OrAttr,AndAttr,Options,SubDir+R.Name,FixedSubDir,Level+1);
     if R2.Count>0 Then
      begin
       if (soResIncludeDir IN Options) Then Res.Add(Format('*%d*',[Level+1])+SubDir+FixedSubDir+R.Name);
       Res.AddStrings(R2);
      end;
     R2.Free; 
    end;
  until FindNext(R)<>0;
end;

end.

Open in new window

0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
Cloud Class® Course: MCSA MCSE Windows Server 2012

This course teaches how to install and configure Windows Server 2012 R2.  It is the first step on your path to becoming a Microsoft Certified Solutions Expert (MCSE).

Emmanuel PASQUIERFreelance Project ManagerCommented:
then you can loop through your files
unit Unit2;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, ExtCtrls;

type
  TForm1 = class(TForm)
    Panel1: TPanel;
    Panel2: TPanel;
    edtText: TEdit;
    Label1: TLabel;
    Label2: TLabel;
    edtDir: TEdit;
    Label3: TLabel;
    edtFileMask: TEdit;
    btnFindFiles: TButton;
    btnSearchText: TButton;
    lbFileList: TListBox;
    mmoSearchResults: TMemo;
    Splitter1: TSplitter;
    btnStopSearch: TButton;
    procedure btnFindFilesClick(Sender: TObject);
    procedure btnSearchTextClick(Sender: TObject);
  private
    { Déclarations privées }
    Dir:String;
    procedure ScanFile(const FN,Text:String);
  public
    { Déclarations publiques }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

Uses untFindFiles;

procedure TForm1.btnFindFilesClick(Sender: TObject);
Var
 FileMask:TStringList;
 i:integer;
begin
 FileMask:=TStringList.Create;
 FileMask.Delimiter:=';';
 FileMask.DelimitedText:=edtFileMask.Text;
 lbFileList.Items.BeginUpdate;
 lbFileList.Items.Clear;
 Dir:=IncludeTrailingBackslash(edtDir.Text);
 for i:=0 to FileMask.Count-1 do FindFiles(Dir,FileMask[i],lbFileList.Items,faAnyFile,0,[soRecurse]);
 lbFileList.Items.EndUpdate;
 FileMask.Free;
end;

procedure TForm1.ScanFile(const FN,Text:String);
 // That function will implement a quick and dirty search. depending on your real needs (multiple search on a same file set)
 // you could try to find a better algorithm that will build some kind of char occurences map once for all search on the same file
 // also, it is CASE SENSITIVE
Var
 F:TStringList;
 i,P:integer;
begin
 mmoSearchResults.ReadOnly:=True;
 mmoSearchResults.Cursor:=crHourGlass;
 Application.ProcessMessages;
 if btnStopSearch.Tag=0 then
  try
   F:=TStringList.Create;
   F.LoadFromFile(Dir+FN);
   for i := 0 to F.Count-1 do
    begin
     P:=Pos(Text,F[i]);
     if P>0 then mmoSearchResults.Lines.Add(Format('%-40s,L%4d.C%3d |%s',[FN,i+1,P,F[i]]));
    end;
  finally
   F.Free;
  end;
 mmoSearchResults.Cursor:=crDefault;
 mmoSearchResults.ReadOnly:=False;
end;

procedure TForm1.btnSearchTextClick(Sender: TObject);
Var
 i:integer;
begin
 if btnSearchText.Visible then
  begin
   btnSearchText.Visible:=False;
   btnStopSearch.Visible:=True;
   btnStopSearch.Tag:=0;
   mmoSearchResults.Clear;
   for i := 0 to lbFileList.Items.Count-1 do
    begin
     lbFileList.ItemIndex:=i;
     ScanFile(lbFileList.Items[i],edtText.Text);
     if btnStopSearch.Tag>0 then break;
    end;
   btnSearchText.Visible:=True;
   btnStopSearch.Visible:=False;
  end Else btnStopSearch.Tag:=1; // Signal 'want to stop'
end;

end.


//=============== DFM

object Form1: TForm1
  Left = 0
  Top = 0
  Caption = 'Form1'
  ClientHeight = 553
  ClientWidth = 869
  Color = clBtnFace
  Font.Charset = DEFAULT_CHARSET
  Font.Color = clWindowText
  Font.Height = -13
  Font.Name = 'Tahoma'
  Font.Style = []
  OldCreateOrder = False
  PixelsPerInch = 96
  TextHeight = 16
  object Splitter1: TSplitter
    Left = 329
    Top = 0
    Width = 6
    Height = 553
  end
  object Panel1: TPanel
    Left = 0
    Top = 0
    Width = 329
    Height = 553
    Align = alLeft
    TabOrder = 0
    ExplicitHeight = 337
    object Panel2: TPanel
      Left = 1
      Top = 1
      Width = 327
      Height = 96
      Align = alTop
      BevelOuter = bvLowered
      TabOrder = 0
      ExplicitWidth = 239
      object Label1: TLabel
        Left = 8
        Top = 11
        Width = 40
        Height = 16
        Caption = 'Search'
      end
      object Label2: TLabel
        Left = 8
        Top = 41
        Width = 44
        Height = 16
        Caption = 'In Dir. :'
      end
      object Label3: TLabel
        Left = 8
        Top = 71
        Width = 54
        Height = 16
        Caption = 'File mask'
      end
      object edtText: TEdit
        Left = 54
        Top = 8
        Width = 267
        Height = 24
        TabOrder = 0
        Text = 'TListBox'
      end
      object edtDir: TEdit
        Left = 54
        Top = 38
        Width = 267
        Height = 24
        TabOrder = 1
        Text = 'D:\Delphi\Projects'
      end
      object edtFileMask: TEdit
        Left = 80
        Top = 68
        Width = 241
        Height = 24
        TabOrder = 2
        Text = '*.pas;*.inc;*.dfm'
      end
    end
    object btnFindFiles: TButton
      Left = 1
      Top = 97
      Width = 327
      Height = 25
      Align = alTop
      Caption = 'Make File List'
      TabOrder = 1
      OnClick = btnFindFilesClick
      ExplicitLeft = 88
      ExplicitTop = 168
      ExplicitWidth = 75
    end
    object btnSearchText: TButton
      Left = 1
      Top = 527
      Width = 327
      Height = 25
      Align = alBottom
      Caption = 'Search Text'
      TabOrder = 2
      OnClick = btnSearchTextClick
      ExplicitLeft = 88
      ExplicitTop = 168
      ExplicitWidth = 75
    end
    object lbFileList: TListBox
      Left = 1
      Top = 122
      Width = 327
      Height = 380
      Align = alClient
      Font.Charset = ANSI_CHARSET
      Font.Color = clBlack
      Font.Height = -13
      Font.Name = 'Courier New'
      Font.Style = []
      ParentFont = False
      TabOrder = 3
      ExplicitLeft = 56
      ExplicitTop = 184
      ExplicitWidth = 121
      ExplicitHeight = 97
    end
    object btnStopSearch: TButton
      Left = 1
      Top = 502
      Width = 327
      Height = 25
      Align = alBottom
      Caption = '!! STOP Search !!'
      TabOrder = 4
      Visible = False
      OnClick = btnSearchTextClick
      ExplicitLeft = 88
      ExplicitTop = 168
      ExplicitWidth = 75
    end
  end
  object mmoSearchResults: TMemo
    Left = 335
    Top = 0
    Width = 534
    Height = 553
    Align = alClient
    Font.Charset = ANSI_CHARSET
    Font.Color = clBlack
    Font.Height = -11
    Font.Name = 'Courier New'
    Font.Style = []
    ParentFont = False
    TabOrder = 1
    ExplicitLeft = 440
    ExplicitTop = 224
    ExplicitWidth = 185
    ExplicitHeight = 89
  end
end

Open in new window

0
Geert GOracle dbaCommented:
you can also use Delphi IDE ...
search in all files, then type the word and the directory
0
rincewind666Author Commented:
Many thanks for your help, which is greatly appreciated.
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Delphi

From novice to tech pro — start learning today.

Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.