匹配路径特征的文件搜索

因为工作原因,需要写一个根据路径特征来获取文件的小工具。问题的描述如下:


已知一个文件名,或者改文件可能位于的某个目录下,我们试图对一个较大的文件夹或者磁盘进行搜索,找到该文件或文件集合的所有位置。

比如说,我们现在有一个色情网站的硬盘盘符为e:\av,这里面分门别类存储了很多很多“你懂得%¥%.avi”,那么我只想获取陈老师的,该如何下手。


需要注意的问题:

一个资源很丰富的目录结构,按照分类的不同,存在不同的结构。假设例子中的av 按照 演员-格式-时间。。。这样的级别来进行归类,那么要找到陈老师,可以很简单的就找到最顶级的文件夹,然后枚举这个文件下下的文件就可以了。但是如果文件时按照  地区-年份-类型-时间-格式-演员这样的级别来划分,那么 陈老师这个目录,估计就要在很多上级目录下进行重复了,这个时候来搜索就不能单纯的进行了。


抽象一下问题:

对于指定的一个树,已知其任意深度k的父亲-孩子节点关系,找出该树中所有匹配该节点关系的路径。


对树的搜索操作经典的方法有两种:深度优先搜索和广度优先搜索。两者在执行复杂度上数量级基本相当。而且都是递归的思想。

在这里采用两种搜索相结合的方式。


以先后关系结合:

1.先采用广度优先搜索,以寻找子目录串的父节点为第一层递归。

2.修改递归条件,进行第二层递归;

3.一直到k层递归条件结束。并使用全局链表list记录下所有满足条件的目录。

4.遍历list里的目录元素,分别对各个目录进行二次搜索,列出全部文件。


其实本来想将第四部整合到前三步的递归中去的。但是递归存在一个致命的问题,就是当前层递归的数据如何保存。

具体表现是:

当对子串的第一个节点(假设为system32)进行匹配之后,需要对下一层递归条件进行修改:搜索变为了system32\abc\,这样就需要把这个结果修改之后,再传递给下一层递归的时候调用。但是我们也知道,在递归程序中,中间结果的数据必须作为局部变量来保存,否则就无法自动满足递归“自己调用自己”的原则,递归就无法进行下去。然而这个局部变量又无法以一个外部变量的身份起到将参数传递到下一层递归里的作用。------这就是一个伪的递归。(也许有比较聪明的解决方法,但是我没有成功。)


具体的操作步骤直接贴代码全文如下:


// filelist.cpp : 定义控制台应用程序的入口点。
//


#include "stdafx.h"
#include "windows.h"
#include "Shlwapi.h"
#include "iostream"
#include "vector"
#include "list"
#include "string"
using namespace std;






void ProbeLinkedDir(LPCSTR lpFile);
bool CheckDir(string file,LPCSTR lpDir);
void SearchFile(LPCSTR lpszPath,LPCSTR lpsubDir);
void SearchFileByDeep(LPCTSTR lpszPath);
std::list<string> listTemps;
vector<string> vecSplit;
vector<string> vecResult;
DWORD count = 0;
int  ndeep = 0;


void Recur(LPCSTR lpszPath,LPCSTR lpsubDir,int nDeep);
int _tmain(int argc, _TCHAR* argv[])
{


//一级目录  目录子串

if(argc != 3)
{
cout<<"DirFilter [-fd] [-sd]\n"
<<"-fd     the parent directory string which desired to be searched.\n"
<<"-sd     the sub-string you used to search\n";
return 0;
}



string sSub(argv[2]);
int nSLen = sSub.length();
int npos  = 0;
string    sPart;
string    sFile;
if(sSub.at(nSLen - 1) != '\\')
{
//说明是末尾,例如  ...\wxp_x86_0804_v1\spcustom.dll.ref
while(((npos = sSub.find("\\")) < nSLen)&&(npos >= 0))
{
sPart = sSub.substr(0,npos);
vecSplit.push_back(sPart);
sSub.erase(0,npos + 1);
}


sFile = sSub;


SearchFile(argv[1],vecSplit.at(0).c_str());


for(list<string>::iterator Pi = listTemps.begin();Pi != listTemps.end();Pi++)
{
string sFullPath = *Pi + sFile;
if(PathFileExists(sFullPath.c_str()))
{
printf("%s\n",sFullPath.c_str());
}


}
}
else
{
//说明特征子串是路径的中间特征值;例如 ...PreInstall\WinSE\ 
while(((npos = sSub.find("\\")) < nSLen)&&(npos >= 0))
{
sPart = sSub.substr(0,npos);
vecSplit.push_back(sPart);
sSub.erase(0,npos + 1);
}


SearchFile(argv[1],vecSplit.at(0).c_str());



for(list<string>::iterator Pi = listTemps.begin();Pi != listTemps.end();Pi++)
{
//printf("%s\n",*Pi);
SearchFileByDeep((*Pi).c_str());
}
}


printf("搜索检测的次数为:%d",count);
return 0;
}


void SearchFileByDeep(LPCTSTR lpszPath)
{
TCHAR strPath[MAX_PATH], strFile[MAX_PATH];
HANDLE hFile;
WIN32_FIND_DATA FindFileData;
wsprintf(strPath, _T("%s*.*"), lpszPath);
hFile = FindFirstFile(strPath, &FindFileData);
if (hFile != INVALID_HANDLE_VALUE)
{
do 
{
if(lstrcmp(FindFileData.cFileName, _T(".")) == 0 || lstrcmp(FindFileData.cFileName, _T("..")) == 0)
continue;
if(FindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
{
//if(lstrcmp(FindFileData.cFileName,"PreInstall") == 0)
// return;


wsprintf(strFile,_T("%s%s\\"), lpszPath, FindFileData.cFileName);
//_tprintf(_T("%s\r\n"),strFile);
SearchFileByDeep( strFile );
}
else
{
wsprintf(strFile,_T("%s%s"), lpszPath, FindFileData.cFileName);
_tprintf(_T("%s\n"),strFile);
}
count++;
} while(FindNextFile(hFile, &FindFileData));
}
if(hFile != INVALID_HANDLE_VALUE)
FindClose(hFile);
}


void SearchFile(LPCSTR lpszPath,LPCSTR lpsubDir)
{
std::vector<string> vecChilds;
TCHAR strPath[MAX_PATH], strFile[MAX_PATH];


HANDLE hFile;
WIN32_FIND_DATA FindFileData;
wsprintf(strPath, _T("%s*.*"), lpszPath);
hFile = FindFirstFile(strPath, &FindFileData);
if (hFile != INVALID_HANDLE_VALUE)
{
do 
{
if (lstrcmp(FindFileData.cFileName, _T(".")) == 0 || lstrcmp(FindFileData.cFileName, _T("..")) == 0)
continue;
if(FindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
{
if(lstrcmp(FindFileData.cFileName, lpsubDir) == 0)
{
wsprintf(strFile,_T("%s%s\\"), lpszPath, FindFileData.cFileName);
//listTemps.push_back(strFile);
//count++;
//return;




//换个思路,一旦找到了一级目录,马上顺次寻找后续目录
ProbeLinkedDir(strFile);
return;
}


wsprintf(strFile,_T("%s%s\\"), lpszPath, FindFileData.cFileName);
//_tprintf(_T("%s\r\n"),strFile);
vecChilds.push_back(strFile);
count++;
}

} while(FindNextFile(hFile, &FindFileData));
}
if(hFile != INVALID_HANDLE_VALUE)
FindClose(hFile);


// 递归其子分组
for (int i=0; i<vecChilds.size(); ++i)
{
SearchFile(vecChilds.at(i).c_str(),lpsubDir);
}
}




void ProbeLinkedDir(LPCSTR lpFile)
{
string file(lpFile);
int nLen = vecSplit.size();


bool flag = true;
for(int i = 1; i < nLen; i++)
{
if(!CheckDir(file,vecSplit.at(i).c_str()))
{
flag = false;
break;
}

file += vecSplit.at(i).c_str();
file += "\\";
}


if(flag == true)
listTemps.push_back(file);
}

bool CheckDir(string file,LPCSTR lpDir)
{
string sPdir = file;
HANDLE hFile;
WIN32_FIND_DATA FindFileData;

file += "\\*.*";
hFile = FindFirstFile(file.c_str(), &FindFileData);
if (hFile != INVALID_HANDLE_VALUE)
{
do 
{
if (lstrcmp(FindFileData.cFileName, _T(".")) == 0 || lstrcmp(FindFileData.cFileName, _T("..")) == 0)
continue;
if(FindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
{
if(lstrcmp(FindFileData.cFileName, lpDir) == 0)
return true;
}


} while(FindNextFile(hFile, &FindFileData));
}
if(hFile != INVALID_HANDLE_VALUE)
FindClose(hFile);


return false;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值