遍历特定目录及其子目录下的所有文件,返回文件名,不能有遗漏,程序该如何修改?

时间:2021-09-19 08:56:45
我需要在一个目录做参数的前提下,遍历此目录及其子目录下的所有文件,返回文件名。我这里有几段代码,一个使用的是WIN32 API(递归算法在 CScanPath_demo的CScanPath::ScanPath函数中。
),另一个使用的是CFileFind(MFC)类的非递归算法。问题是这些算法枚举的文件都不全,有遗漏。问题的出现是否与某一MFC函数或WIN32 API执行失败有关。请帮助我找出其中一个算法的错误。或是给我一个其他正确的算法。最好能有完整的可执行的工程文件。谢谢!

/************************************************************************/
/* Recursive files scanner function                                      */
/************************************************************************/
void CScanPath::ScanPath( char *rep, int mode )
{
WIN32_FIND_DATA FindFileData; 
    char path[MAX_PATH];   
HANDLE hFind;   
DWORD a = 0;   

if( m_bStop )
return;

    strncpy( path, rep, MAX_PATH - 1 );
    strncat( path, "\\*.*", MAX_PATH - strlen(path) - 1 );

// recherche le premier fichier
    hFind = FindFirstFile(path, &FindFileData);
    if (hFind==INVALID_HANDLE_VALUE)
        return;

    if (strcmp(FindFileData.cFileName,".")!=0 && strcmp(FindFileData.cFileName,"..")!=0)
    {
        strncpy( path, rep, MAX_PATH - 1 );
        strncat( path, "\\", MAX_PATH - strlen(path) - 1 );
        strncat( path, FindFileData.cFileName, MAX_PATH - strlen(path) - 1 );
        ScanPath( path, mode );
    }
  
    while (a != ERROR_NO_MORE_FILES && !m_bStop )
    {
        if (!FindNextFile(hFind, &FindFileData))
            a = GetLastError();
        else
        {
            if (strcmp(FindFileData.cFileName,".")!=0 && strcmp(FindFileData.cFileName,"..")!=0)
            {
                strncpy( path, rep, MAX_PATH - 1 );
                strncat( path, "\\", MAX_PATH - strlen(path) - 1 );
                strncat( path, FindFileData.cFileName, MAX_PATH - strlen(path) - 1 );

                if (FindFileData.dwFileAttributes == FILE_ATTRIBUTE_DIRECTORY)
{
                    ScanPath(path, mode );
}
                else
                {
if( mode & MODE_FUNC )
m_ScanPathCallBack( path );

else
{
if( mode & MODE_COUNT )
m_dwFilesCount++;

if( mode & MODE_SIZE )
m_dwFilesSizes+=(FindFileData.nFileSizeHigh * ((long)MAXDWORD+1) + FindFileData.nFileSizeLow);
}
                }
            }
        }
    }
    FindClose(hFind);

}
//非递归算法
void ProcessDirectory(LPCTSTR dirname)
{   long count=0;
     CStringArray dirs;
     CString searchname;
     CFileFind find;
     dirs.Add(dirname);
     BOOL bRet;
     while(dirs.GetSize()>0)
     {
        
        searchname = dirs[0] +"\\*.*";
        dirs.RemoveAt(0);
        bRet = find.FindFile (searchname,0);
        if(!bRet)continue;
        do{
            bRet = find.FindNextFile ();
            if(find.IsDots ())
            {//忽略.和..文件
                continue;
            }
            if(find.IsDirectory ())
            {
                dirs.Add (find.GetFilePath());
                continue;
            }else{
                
                {  

find.GetFilePath ();
                    count++;
std::cout<<find.GetFilePath ()<<std::endl;
                }
            }
        }while(bRet);
     }
 std::cout<<count;
}

8 个解决方案

#1


你先说清楚遗漏什么文件了?

#2


 关注……

#3


是这个目录:
c:\Program Files\Microsoft Visual Studio .NET 2003\SDK\v1.1\Tool Developers Guide\docs\Partition II Metadata.doc 在哪个递归算法中便利不到。

#4


,学习,关注~~~~

#5


BOOL DeleteDirectory(LPCTSTR DirName)
  {
   CFileFind tempFind; //声明一个CFileFind类变量,以用来搜索
   char tempFileFind[200]; //用于定义搜索格式
   sprintf(tempFileFind,"%s\\*.*",DirName);
   //匹配格式为*.*,即该目录下的所有文件 
 
   BOOL IsFinded=(BOOL)tempFind.FindFile(tempFileFind);
   //查找第一个文件
   while(IsFinded)
   {
    IsFinded=(BOOL)tempFind.FindNextFile(); //递归搜索其他的文件
    if(!tempFind.IsDots()) //如果不是"."目录
    {
     char foundFileName[200];
     strcpy(foundFileName,tempFind.GetFileName().GetBuffer(200));
     if(tempFind.IsDirectory()) //如果是目录,则递归地调用
     { 
      //DeleteDirectory
      char tempDir[200];
      sprintf(tempDir,"%s\\%s",DirName,foundFileName);
      DeleteDirectory(tempDir);
     }
     else
     { 
      //如果是文件则直接删除之
      char tempFileName[200];
      sprintf(tempFileName,"%s\\%s",DirName,foundFileName);
      DeleteFile(tempFileName);
     }
    }
   }
   tempFind.Close();
   if(!RemoveDirectory(DirName)) //删除目录
   {
    AfxMessageBox("删除目录失败!",MB_OK);
    return FALSE;
   }
   return TRUE;
  }

============================================
递归删除的(未测试)

#6



void CAviConvertToolDlg::BrowseDir( LPTSTR strDir)
{    
    CString szDir;
    szDir.Format( _T("%s\\*.*"), strDir);

    CFileFind find;
    BOOL bFind = find.FindFile(szDir.GetBuffer(0));
    while(bFind)
    {
        bFind = find.FindNextFile();

        if(find.IsDots())
        {
            continue;
        }
        if(find.IsDirectory())
        {
            CString szDirectoryName;
            szDirectoryName = find.GetFilePath();

            if((GetFileAttributes(szDirectoryName) & FILE_ATTRIBUTE_DIRECTORY)
                &&!(GetFileAttributes(szDirectoryName)&FILE_ATTRIBUTE_SYSTEM))  
 //避开隐藏文件夹 或者 系统文件夹(有时候系统文件夹是禁止访问的),你可以自己修改遍历的条件
            {
                BrowseDir(szDirectoryName.GetBuffer(0));
            }

        }
        CString szFileDir;
        CString szFileName;
        CString szFileExtendName;

        szFileDir = find.GetFilePath();
        szFileName = find.GetFileName();
        szFileExtendName = szFileName;

       // szFileExtendName.Replace(find.GetFileTitle(),_T(''));
      //  if(_tcscmp(szFileExtendName,_T(".txt"))!= 0)
       // {
      //      continue;
     //   }
        m_lstAviConvertSourceFile.AddString(szFileDir);//这句是我操作的,你在这可以进行你所需要的操作了

    }
    find.Close();
}


#7


感觉用IShellFolder会简单一些,你可以搜一下MSDN上有例子

#8


    感谢您的回复!
    如果我要测试您给我提供的算法该用什么测试用例呢?如果我用输入某一指定路径,运行程序。然后将输出与同样输入下windows2000提供的文件搜索工具进行的输出进行比较,方法是否合适呢?

#1


你先说清楚遗漏什么文件了?

#2


 关注……

#3


是这个目录:
c:\Program Files\Microsoft Visual Studio .NET 2003\SDK\v1.1\Tool Developers Guide\docs\Partition II Metadata.doc 在哪个递归算法中便利不到。

#4


,学习,关注~~~~

#5


BOOL DeleteDirectory(LPCTSTR DirName)
  {
   CFileFind tempFind; //声明一个CFileFind类变量,以用来搜索
   char tempFileFind[200]; //用于定义搜索格式
   sprintf(tempFileFind,"%s\\*.*",DirName);
   //匹配格式为*.*,即该目录下的所有文件 
 
   BOOL IsFinded=(BOOL)tempFind.FindFile(tempFileFind);
   //查找第一个文件
   while(IsFinded)
   {
    IsFinded=(BOOL)tempFind.FindNextFile(); //递归搜索其他的文件
    if(!tempFind.IsDots()) //如果不是"."目录
    {
     char foundFileName[200];
     strcpy(foundFileName,tempFind.GetFileName().GetBuffer(200));
     if(tempFind.IsDirectory()) //如果是目录,则递归地调用
     { 
      //DeleteDirectory
      char tempDir[200];
      sprintf(tempDir,"%s\\%s",DirName,foundFileName);
      DeleteDirectory(tempDir);
     }
     else
     { 
      //如果是文件则直接删除之
      char tempFileName[200];
      sprintf(tempFileName,"%s\\%s",DirName,foundFileName);
      DeleteFile(tempFileName);
     }
    }
   }
   tempFind.Close();
   if(!RemoveDirectory(DirName)) //删除目录
   {
    AfxMessageBox("删除目录失败!",MB_OK);
    return FALSE;
   }
   return TRUE;
  }

============================================
递归删除的(未测试)

#6



void CAviConvertToolDlg::BrowseDir( LPTSTR strDir)
{    
    CString szDir;
    szDir.Format( _T("%s\\*.*"), strDir);

    CFileFind find;
    BOOL bFind = find.FindFile(szDir.GetBuffer(0));
    while(bFind)
    {
        bFind = find.FindNextFile();

        if(find.IsDots())
        {
            continue;
        }
        if(find.IsDirectory())
        {
            CString szDirectoryName;
            szDirectoryName = find.GetFilePath();

            if((GetFileAttributes(szDirectoryName) & FILE_ATTRIBUTE_DIRECTORY)
                &&!(GetFileAttributes(szDirectoryName)&FILE_ATTRIBUTE_SYSTEM))  
 //避开隐藏文件夹 或者 系统文件夹(有时候系统文件夹是禁止访问的),你可以自己修改遍历的条件
            {
                BrowseDir(szDirectoryName.GetBuffer(0));
            }

        }
        CString szFileDir;
        CString szFileName;
        CString szFileExtendName;

        szFileDir = find.GetFilePath();
        szFileName = find.GetFileName();
        szFileExtendName = szFileName;

       // szFileExtendName.Replace(find.GetFileTitle(),_T(''));
      //  if(_tcscmp(szFileExtendName,_T(".txt"))!= 0)
       // {
      //      continue;
     //   }
        m_lstAviConvertSourceFile.AddString(szFileDir);//这句是我操作的,你在这可以进行你所需要的操作了

    }
    find.Close();
}


#7


感觉用IShellFolder会简单一些,你可以搜一下MSDN上有例子

#8


    感谢您的回复!
    如果我要测试您给我提供的算法该用什么测试用例呢?如果我用输入某一指定路径,运行程序。然后将输出与同样输入下windows2000提供的文件搜索工具进行的输出进行比较,方法是否合适呢?