⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 unit2.cpp

📁 多线程文件搜索源程序
💻 CPP
字号:
//---------------------------------------------------------------------------
#include <vcl.h>
#pragma hdrstop

#include "Unit2.h"
#include "Unit1.h"
#pragma package(smart_init)
//---------------------------------------------------------------------------

//   Important: Methods and properties of objects in VCL can only be
//   used in a method called using Synchronize, for example:
//
//      Synchronize(UpdateCaption);
//
//   where UpdateCaption could look like:
//
//      void __fastcall Unit2::UpdateCaption()
//      {
//        Form1->Caption = "Updated in a thread";
//      }
//---------------------------------------------------------------------------
//线程构造函数
__fastcall TSearchFileThread::TSearchFileThread(bool CreateSuspended,
    AnsiString pFileDir,AnsiString pFilter,AnsiString pSeekText,
    bool pSubdirEnabled): TThread(true)
{
    //线程终止自动释放内存
    FreeOnTerminate = true;
    //初始化成员变量
    mFileDir=pFileDir;
    mFilter=pFilter;
    mSeekText=pSeekText;
    mSubdirEnabled=pSubdirEnabled;
    //挂起方式启动线程
    Resume();
}
//---------------------------------------------------------------------------
//线程Execute方法
void __fastcall TSearchFileThread::Execute()
{
    //响应线程终止事件
    OnTerminate=Form1->ThreadOnEnd;
    //现程中断属性无效时持续循环
    FindFile(mFileDir,mFilter,mSeekText,mSubdirEnabled);

}
//---------------------------------------------------------------------------
//自定义成员函数,查找指定子文件夹下符合搜索条件的文件,可被递归调用
bool __fastcall TSearchFileThread::FindFile(AnsiString FileDir,
    AnsiString Filter,AnsiString SeekText,bool SubdirEnabled)
{
    AnsiString str;
    //定义查找文件API函数中用到的数据结构
    WIN32_FIND_DATA FindFileData;
    //取出文件目录名的最后一个字符
    str=FileDir.SubString(FileDir.Length(),1);
    //文件夹中第一、二条记录的情况
    if(str==".")return true;
    //文件目录名的最后一个字符不是“\”,添加“\”
    //如FileName为“C:\Windows” 变换后为“C:\Windows\”
    if(str!="\\")FileDir+="\\";
    //拟查找的文件为“*.*”类型,即文件夹中所有文件
    str=FileDir+AnsiString("*.*");
    //用API函数查找第一个类型匹配的函数
    HANDLE hFile=FindFirstFile(str.c_str(),&FindFileData);
    //线程不被终止及找到文件时循环
    while(!Terminated&&hFile)
    {
        //取文件全名,即路径名+文件名,此时尚不知是普通文件还是文件夹等
        str=FileDir+FindFileData.cFileName;
        //属普通文件的情况...
        if((FindFileData.dwFileAttributes&0x00ff)==0x20)
        {
            //属文件类型匹配,且文件中包含待找文本的情况...
            if(FilterFile(str,Filter)&&LocateFile(str,SeekText))
            {
                //str文件全名存到线程的成员变量OutputFileName
                mOutputFileName = str;
                //借助于同步函数Synchronize,将当前文件全名添加到主窗口的放置已
                //找到文件列表的Tmemo控件,具体由自定义成员函数IntoFileList完成
                //与VCL打交道必须用Synchronize,且要求IntoFileList无自变量无返回值
                Synchronize(IntoFileList);
            }
        }
        //允许“包含子文件夹”且当前文件全名为子目录的情况...
        else if(SubdirEnabled&&(FindFileData.dwFileAttributes&0x00ff)==0x10)
        {
            //子目录下又遇到子目录,递归调用,即函数自己调用自己
            FindFile(str,Filter,SeekText,SubdirEnabled);
        }
        //对应于API函数FindFirstFile,下面调用另一API函数查找后续的类型匹配文件
        if(FindNextFile(hFile,&FindFileData)==false)
        {
            //再也找不到,跳出循环
            break;
        }
    }
    return true;
}
//---------------------------------------------------------------------------
//文件类型过滤,Filter可能为“*.*”“*.htm”等,不支持“?”弘代换字符
//FileName若为Filter指定的类型返回true,否则返回false
bool __fastcall TSearchFileThread::FilterFile(AnsiString FileName,
    AnsiString Filter)
{
    AnsiString str;
    //Filter未指定过滤条件时,属类型匹配方式,返回true
    if(Filter.IsEmpty())return true;
    int pos=Filter.AnsiPos(".");
    if(pos==0)
    {
        //属指定文件名的情况,仅当FileName与Filter相同,返回true
        if(FileName==Filter)return true;
    }
    else
    {
        //取出类型串中文件扩展名部分,如“*.htm”的“.htm”
        str=Filter.SubString(pos,Filter.Length());
        //属于“*.*”的情况
        if(str==".*")return true;
        //调用取出文件名的扩展名的系统函数,判断文件类型是否相同
        if(ExtractFileExt(FileName).UpperCase()==str.UpperCase())return true;
    }
    return false;
}
//---------------------------------------------------------------------------
//判断文件FileName是否包含文本SeekText,包含返回true,否则返回false
bool __fastcall TSearchFileThread::LocateFile(AnsiString FileName,
    AnsiString SeekText)
{
    //声明流式文件
    TFileStream * pFile;
    try
    {
        //只读方式打开文件,不能正确打开时抛出异常
        pFile=new TFileStream(FileName,fmOpenRead);
    }
    catch(...)
    {
        //打开文件异常,中途退出,返回false,与不包含待查文本情况同
        return false;
    }
    char *buffer;
    try
    {
        //尝试方式申请分配与流式文件相同长度的内存缓冲区
        buffer=new char[pFile->Size];
    }
    catch(...)
    {
        //内存分配申请失败,关闭流式文件
        delete pFile;
        //中途退出,返回false,与不包含待查文本情况同
        return false;
    }
    //将流式文件全部读入内存缓冲区
    pFile->Read(buffer,pFile->Size);
    //将buffer构造为AnsiString串,并用其子串索引方法查找SeekText
    int pos=AnsiString(buffer,pFile->Size).AnsiPos(SeekText);

    //关闭流式文件
    delete pFile;
    //释放内存
    delete buffer;
    //文件中未找到待找文本,返回false
    if(pos==0)return false;
    //文件中已找到待找文本,返回true
    return true;
}
//---------------------------------------------------------------------------
//搜索到符合条件的文件送主窗口列表框
void __fastcall TSearchFileThread::IntoFileList(void)
{
    //文件名添加到主窗口的列表框中
    Form1->ListBox1->Items->Add(mOutputFileName);
}
//---------------------------------------------------------------------------

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -