WEB开发网
开发学院软件开发Delphi 多线程操作一例:查找 pas dfm 里的中文 阅读

多线程操作一例:查找 pas dfm 里的中文

 2010-11-02 17:06:58 来源:WEB开发网   
核心提示:查找一个pas文件里的汉字,需要打开此文件,多线程操作一例:查找 pas dfm 里的中文,逐行读出,判断,在添加一个TCNFile文件时需要进行同步,否则会造成同时访问FFiles出错,查找 dfm 与上相似,但dfm里的汉字是使用数值来表示的

查找一个pas文件里的汉字,需要打开此文件,逐行读出,判断。

查找 dfm 与上相似,但dfm里的汉字是使用数值来表示的,需要用widechar转换过来。此外汉字开始标记为 "#" (不准确)。

程序实现

1、TFileLine 一行文字

2、TCNFile 一个含有汉字的文件

3、TFolder 一个文件夹

4、TFileThread 文件处理线程

注释

使用标准文件查找的方式进行文件查找,遇到pas或dfm文件时,开启线程对其操作(此处为异步线程)。关于线程同步,在添加一个TCNFile文件时需要进行同步,否则会造成同时访问FFiles出错。

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, ExtCtrls, ComCtrls,Contnrs,SyncObjs, ImgList,
  RzStatus, RzPanel;

type

  TFileLine = class
  private
    FLine:Integer;
    FContext:String;
  public
    { 功能:行号}
    property  Line:Integer read FLine write FLine;
    { 功能:内容}
    property  Context:String read FContext write FContext;
  end;

  TCNFile = class
  private
    FHashCN:Boolean;
    FContexts:TObjectList;
    FName:string;
    function GetCount:Integer;
    function GetContexts(const Index:integer):TFileLine;
  public
    destructor destroy;override;
    { 功能:含有中文}
    property  HashCN:Boolean read FHashCN write FHashCN;
    { 功能:文件名}
    property  Name:string read FName write FName;
    { 功能:添加}
    function  Add:TFileLine;
    { 功能:数量}
    property  Count:Integer read GetCount;
    { 功能:内容}
    property  Contexts[const Index:integer]:TFileLine read GetContexts;
  end;

  TFolder = class
  private
    FFiles:TObjectList;
    FFolders:TObjectList;
    FCS:TCriticalSection;
    FName:string;
    function GetCount:Integer;
    function GetFiles(const Index:integer):TCNFile;
    function GetFolderCount:Integer;
    function GetFolders(const Index:integer):TFolder;
  public
    constructor Create;
    destructor  Destroy;override;
    { 功能:文件夹名}
    property  Name:string read FName write FName;
    { 功能:添加}
    function  Add:TCNFile;
    function  AddFoler:TFolder;
    { 功能:数量}
    property  Count:Integer read GetCount;
    { 功能:内容}
    property  Files[const Index:integer]:TCNFile read GetFiles;
    { 功能:数量}
    property  FolderCount:Integer read GetFolderCount;
    { 功能:内容}
    property  Folders[const Index:integer]:TFolder read GetFolders;
  end;
//  PFileRec = ^TFileRec;
//  TFileRec = record
//    Data:TCNFile;
//  end;

  TFileMethod = procedure (const Folder:TFolder;const FileName:string) of object;

  TFileThread = class(TThread)
  private
    FFolder:TFolder;
    FFileName:String;
    FMethod:TFileMethod;
  protected
    procedure Execute;override;
  public
    { 功能:文件夹}
    property  Folder:TFolder read FFolder write FFolder;
    { 功能:文件}
    property  FileName:String read FFileName write FFileName;
    { 功能:方法}
    property  Method:TFileMethod read FMethod write FMethod;
  end;


  TForm1 = class(TForm)
    Panel1: TPanel;
    Splitter1: TSplitter;
    Memo1: TMemo;
    Label1: TLabel;
    edt_Path: TEdit;
    Button1: TButton;
    TreeView1: TTreeView;
    ImageList1: TImageList;
    GroupBox1: TGroupBox;
    cb_include: TCheckBox;
    cb_Svn: TCheckBox;
    cb_Dcu: TCheckBox;
    RzStatusBar1: TRzStatusBar;
    stProgress: TRzProgressStatus;
    cb_CN: TCheckBox;
    stText: TRzStatusPane;
    procedure Button1Click(Sender: TObject);
    procedure TreeView1Click(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
    procedure TreeView1DblClick(Sender: TObject);
    procedure edt_PathDblClick(Sender: TObject);
    procedure cb_CNClick(Sender: TObject);
    procedure stTextDblClick(Sender: TObject);
  private
    ThreadCount:Integer;
    FileCount:Integer;
    FLast:TTreeNode;
    FCS:TCriticalSection;
    Root:TFolder;
    procedure SearchProc(const Parent:TFolder;const Path:string);
    procedure DoFile(const Folder:TFolder;const FileName:string);
    procedure ThreadEnd(sender:TObject);
    procedure MakeTree;
    procedure WaitFor;
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation
uses
  BrowseForFolderU,ShellAPI;
{$R *.dfm}

{ TForm1 }

procedure TForm1.SearchProc(const Parent:TFolder;const Path:string);
  function GetFolderName:string;
  var
    i:Integer;
  begin
    i:=Length(ExtractFileDir(Path));
    Result:=Path;
    Delete(Result,1,i + 1);
  end;
var
  SearchRec: TSearchRec;
  iResult:Integer;
  extName:string;
  _Path:string;
  _Folder:TFolder;
  _FileThread:TFileThread;
begin
  if not DirectoryExists(Path) then Exit;
  _Path:=Path;
  if Path[Length(Path)] <> '\' then
    _Path:=Path + '\';
//  if Assigned(Parent) then
  _Folder:=Parent.AddFoler;
  _Folder.Name:=GetFolderName;
  iResult:=FindFirst(_Path + '*.*', faAnyFile, SearchRec);
  while iResult = 0 do
  begin
    if (SearchRec.Attr and faDirectory = faDirectory)  then
    begin
      if (SearchRec.Name <> '.') and (SearchRec.Name <> '..') then
      begin
        if cb_Svn.Checked and SameText(SearchRec.Name,'.svn') then
        begin
          iResult:=FindNext(SearchRec);
          Continue;
        end;
        if cb_Dcu.Checked and SameText(SearchRec.Name,'.dcu') then
        begin
          iResult:=FindNext(SearchRec);
          Continue;
        end;
        if cb_include.Checked then
          SearchProc(_Folder,_Path + SearchRec.Name);
      end;
    end
    else
    begin
      extName:=ExtractFileExt(SearchRec.Name);
      if SameText(extName,'.pas') or SameText(extName,'.dfm') then
      begin
        Inc(FileCount);
        stProgress.PartsComplete:= FileCount ;
        stProgress.Update;
        _FileThread:=TFileThread.Create(True);
        _FileThread.Folder:=_Folder;
        _FileThread.FileName:=_Path + SearchRec.Name;
        _FileThread.Method:=DoFile;
        _FileThread.OnTerminate:=ThreadEnd;
        Inc(ThreadCount);
        _FileThread.Resume;
        _FileThread.WaitFor;
      end;
    end;
    iResult:=FindNext(SearchRec);
  end;
  FindClose(SearchRec);
end;

procedure TForm1.DoFile(const Folder: TFolder; const FileName: string);
  function getCN(s:string):string;
  var
    i:Integer;
    tmp:string;
  begin
    Result:='''';
    i:=Pos('#',s);
    while i>0 do
    begin
      tmp:=Copy(s,1,i - 1);
      Delete(s,1,i);
      Result:=Result + WideChar(StrToInt(tmp));
      i:=Pos('#',s);
    end;
    Result:=Result + WideChar(StrToInt(s)) + '''';
  end;  
var
  _File:TextFile;
  Line:string;
  i:Integer;
  AFile:TCNFile;
  _Line:TFileLine;
  LineNum:Integer;
  s:string;
begin
  if not Assigned(Folder) then Exit;
  AssignFile(_File,FileName);
  AFile:=Folder.Add;
  AFile.Name:=FileName;
  LineNum:=0;
  try
    Reset(_File);
    while not Eof(_File) do
    begin
      Inc(LineNum);
      Readln(_File,Line);
      for i:=1 to Length(Line) do
      begin
        if (Ord(Line[i]) > 127) then
        begin
          AFile.HashCN:=True;
          _Line:=AFile.Add;
          _Line.Line:=LineNum;
          _Line.Context:=Line;
          Break;
        end
        else if (Line[i] = '#') then
        begin
          AFile.HashCN:=True;
          _Line:=AFile.Add;
          _Line.Line:=LineNum;
          s:=Copy(Line,i + 1,MaxInt);
          _Line.Context:=Copy(Line,1,i - 1) + getCN(s);
          Break;
        end;  
      end;  
    end;  
  finally
    CloseFile(_File);
  end;   
end;

procedure TForm1.MakeTree;
  procedure AddFile(const Node:TTreeNode;const Folder:TFolder);
  var
    i:Integer;
    _File:TCNFile;
    _Node:TTreeNode;
  begin
    for i:=0 to Folder.Count - 1 do
    begin
      _File:=TCNFile(Folder.Files[i]);
      if cb_CN.Checked then
        if not _File.HashCN then
          Continue;
      _Node:=TreeView1.Items.AddChild(Node,ExtractFileName(_File.Name));
      _Node.Data:=_File;
      if _File.HashCN then
      begin
        _Node.ImageIndex:=1;
        _Node.SelectedIndex:=1;
      end
      else
      begin
        _Node.ImageIndex:=2;
        _Node.SelectedIndex:=2;
      end;
    end;
  end;
  
  procedure AddFolder(const Parent:TTreeNode;const Folder:TFolder);
  var
    i:Integer;
    _Folder:TFolder;
    _Node:TTreeNode;
  begin
    _Node:=TreeView1.Items.AddChild(Parent,Folder.Name);
    _Node.ImageIndex:=0;
    _Node.SelectedIndex:=0;
//    _Node.Data:=Folder;
    AddFile(_Node,Folder);
    for i:=0 to Folder.FolderCount - 1 do
    begin
      _Folder:=TFolder(Folder.Folders[i]);
      AddFolder(_Node,_Folder);
    end;
    _Node.Expand(True);
  end;

begin
//  TreeView1.Items.BeginUpdate;
  AddFolder(nil,Root);
//  TreeView1.Items.EndUpdate;
end;

procedure TForm1.WaitFor;
begin
  Screen.Cursor:=crHourGlass;
//  Sleep(100);
  while ThreadCount > 0 do
  begin
    OutputDebugString(PChar('== ' + IntToStr(ThreadCount)));
    Sleep(10);
  end;
  stProgress.Percent:=0;
  MakeTree;
  Screen.Cursor:=crDefault;
end;

procedure TForm1.ThreadEnd(sender: TObject);
begin
  Dec(ThreadCount);
end;

{ TCNFile }

function TCNFile.Add: TFileLine;
begin
  Result:=TFileLine.Create;
  if not Assigned(FContexts) then
    FContexts:=TObjectList.Create;
  FContexts.Add(Result);
end;

destructor TCNFile.destroy;
begin
  if Assigned(FContexts) then
    FContexts.Free;
end;

function TCNFile.GetContexts(const Index: integer): TFileLine;
begin
  Result:=nil;
  if Index in [0..Count-1] then
    Result:=TFileLine(FContexts.Items[Index]);
end;

function TCNFile.GetCount: Integer;
begin
  Result:= -1 ;
  if Assigned(FContexts) then
    Result:=FContexts.Count;
end;

{ TFolder }

function TFolder.Add: TCNFile;
begin
  FCS.Enter;
  Result:=TCNFile.Create;
  if not Assigned(FFiles) then
    FFiles:=TObjectList.Create;
  FFiles.Add(Result);
  FCS.Leave;
end;

function TFolder.AddFoler: TFolder;
begin
  Result:=TFolder.Create;
  if not Assigned(FFolders) then
    FFolders:=TObjectList.Create;
  FFolders.Add(Result);
end;

constructor TFolder.Create;
begin
  FCS:=TCriticalSection.Create;
end;

destructor TFolder.Destroy;
begin
  if Assigned(FFiles) then
    FFiles.Free;
  if Assigned(FFolders) then
    FFolders.Free;
  FCS.Free;
  inherited;
end;

function TFolder.GetCount: Integer;
begin
  Result:= -1 ;
  if Assigned(FFiles) then
    Result:=FFiles.Count;
end;

function TFolder.GetFiles(const Index: integer): TCNFile;
begin
  Result:=nil;
  if Index in [0..Count-1] then
    Result:=TCNFile(FFiles.Items[Index]);
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  TreeView1.Items.Clear;
  if Assigned(Root) then
    FreeAndNil(Root);
  Root:=TFolder.Create;
  Root.Name:='搜索结果';
  SearchProc(Root,edt_Path.Text);
  WaitFor;
end;

function TFolder.GetFolderCount: Integer;
begin
  Result:= -1 ;
  if Assigned(FFolders) then
    Result:=FFolders.Count;
end;

function TFolder.GetFolders(const Index: integer): TFolder;
begin
  Result:=nil;
  if Index in [0..FolderCount-1] then
    Result:=TFolder(FFolders.Items[Index]);
end;

{ TFileThread }

procedure TFileThread.Execute;
begin
//  FreeOnTerminate:=True;
  if Assigned(FMethod) then
    FMethod(FFolder,FFileName);
end;

procedure TForm1.TreeView1Click(Sender: TObject);
var
  item:TTreeNode;
  i:Integer;
  _File:TCNFile;
  _Line:TFileLine;
  Count:Integer;
begin
  item:=TreeView1.Selected;
  if FLast = item then Exit;
  FLast:=item;
  FCS.Enter;
  if not Assigned(item) then Exit;
  if Assigned(item.Data) then
  begin
//    if item.Data is TCNFile then
    begin
      Memo1.Lines.BeginUpdate;
      Memo1.Lines.Clear;
      _File:=TCNFile(item.Data);
      stText.Caption:=_File.Name;
      if _File.Count > 50 then
        Count:=50
      else
        Count:=_File.Count;
      for i:=0 to Count -1 do
      begin
        _Line:=_File.Contexts[i];
        Memo1.Lines.Add('行号:' + IntToStr(_Line.Line));
        Memo1.Lines.Add(_Line.Context);
        Memo1.Lines.Add('');
      end;
      Memo1.Lines.EndUpdate;
    end;  
  end;
  FCS.Leave; 
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  FCS:=TCriticalSection.Create;
end;

procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  FCS.Free;
  if Assigned(Root) then
    Root.Free;
end;

procedure TForm1.TreeView1DblClick(Sender: TObject);
var
  item:TTreeNode;
begin
  item:=TreeView1.Selected;
  if not Assigned(item) then Exit;
  if Assigned(item.Data) then
    WinExec(PChar('notepad.exe ' + TCNFile(item.Data).Name),SW_SHOW);
end;

procedure TForm1.edt_PathDblClick(Sender: TObject);
var
  outMsg: string;
  OldPath,_Path:string;
begin
  outMsg := '选择目录';
  OldPath:=edt_Path.Text;
  _Path := BrowseForFolder(outMsg, OldPath);
  if _Path = EmptyStr then
    _Path:=OldPath;
  edt_Path.Text:=_Path;
end;

procedure TForm1.cb_CNClick(Sender: TObject);
begin
  TreeView1.Items.BeginUpdate;
  TreeView1.Items.Clear;
  MakeTree;
  TreeView1.Items.EndUpdate;
end;

procedure TForm1.stTextDblClick(Sender: TObject);
var
  _file:string;
begin
  _file:=stText.Caption;
  if FileExists(_file) then
    ShellExecute(Handle,PChar('Open'),PChar(_file),nil,nil,SW_SHOWNORMAL);
end;

end.

多线程执行长时间的任务,客户端显示出任务的执行进度的示例

http://tech.cncms.com/web/aspnet/109280.html

Tags:多线程 pas dfm

编辑录入:爽爽 [复制链接] [打 印]
赞助商链接