vc提供的遍历目录的函数 FindFirstFile

来源:互联网 发布:网络物理隔离卡 编辑:程序博客网 时间:2024/05/21 20:25

VC声明

  HANDLE FindFirstFile(  LPCTSTR lpFileName, // file name  LPWIN32_FIND_DATA lpFindFileData // data buffer  );

功能说明

  该函数到一个文件夹(包括子文件夹)去搜索指定文件 如果要使用附加属性去搜索文件的话 可以使用FindFirstFileEx函数

参数说明

  HANDLE hFindFile搜索的文件句柄 函数执行的时候搜索的是此句柄的下一文件  LPWIN32_FIND_DATA lpFindFileData 指向一个用于保存文件信息的结构体

返回值

  如果调用成功返回一个句柄,可用来做为FindNextFile或FindClose参数  调用失败 返回为INVALID_HANDLE_VALUE(即-1) ,可调用GetLastError来获取错误信息


在此要注意的是返回为INVALID_HANDLE_VALUE时 表明的是调用函数失败


上msdn上的代码 一目了然:

  #include <windows.h>
  #include <tchar.h>
  #include <stdio.h>
  #include <strsafe.h>
 
  void DisplayErrorBox(LPTSTR lpszFunction);
 
  int _tmain(int argc, TCHAR *argv[])
  {
     WIN32_FIND_DATA ffd;
     LARGE_INTEGER filesize;
     TCHAR szDir[MAX_PATH];
     size_t length_of_arg;
     HANDLE hFind = INVALID_HANDLE_VALUE;
     DWORD dwError=0;
     
     // If the directory is not specified as a command-line argument,
     // print usage.
 
     if(argc != 2)
     {
        _tprintf(TEXT("\nUsage: %s <directory name>\n"), argv[0]);
        return (-1);
     }
 
     // Check that the input path plus 3 is not longer than MAX_PATH.
     // Three characters are for the "\*" plus NULL appended below.
 
     StringCchLength(argv[1], MAX_PATH, &length_of_arg);
 
     if (length_of_arg > (MAX_PATH - 3))
     {
        _tprintf(TEXT("\nDirectory path is too long.\n"));
        return (-1);
     }
 
     _tprintf(TEXT("\nTarget directory is %s\n\n"), argv[1]);
 
     // Prepare string for use with FindFile functions.  First, copy the
     // string to a buffer, then append '\*' to the directory name.
 
     StringCchCopy(szDir, MAX_PATH, argv[1]);
     StringCchCat(szDir, MAX_PATH, TEXT("\\*"));
 
     // Find the first file in the directory.
 
     hFind = FindFirstFile(szDir, &ffd);
 
     if (INVALID_HANDLE_VALUE == hFind)
     {
        DisplayErrorBox(TEXT("FindFirstFile"));
        return dwError;
     }
     
     // List all the files in the directory with some info about them.
 
     do
     {
        if (ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
        {
           _tprintf(TEXT("  %s   <DIR>\n"), ffd.cFileName);
        }
        else
        {
           filesize.LowPart = ffd.nFileSizeLow;
           filesize.HighPart = ffd.nFileSizeHigh;
           _tprintf(TEXT("  %s   %ld bytes\n"), ffd.cFileName, filesize.QuadPart);
        }
     }
     while (FindNextFile(hFind, &ffd) != 0);
   
     dwError = GetLastError();
     if (dwError != ERROR_NO_MORE_FILES)
     {
        DisplayErrorBox(TEXT("FindFirstFile"));
     }
 
     FindClose(hFind);
     return dwError;
  }
 
 
  void DisplayErrorBox(LPTSTR lpszFunction)
  {
      // Retrieve the system error message for the last-error code
 
      LPVOID lpMsgBuf;
      LPVOID lpDisplayBuf;
      DWORD dw = GetLastError();
 
      FormatMessage(
          FORMAT_MESSAGE_ALLOCATE_BUFFER |
          FORMAT_MESSAGE_FROM_SYSTEM |
          FORMAT_MESSAGE_IGNORE_INSERTS,
          NULL,
          dw,
          MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
          (LPTSTR) &lpMsgBuf,
          0, NULL );
 
      // Display the error message and clean up
 
      lpDisplayBuf = (LPVOID)LocalAlloc(LMEM_ZEROINIT,
          (lstrlen((LPCTSTR)lpMsgBuf)+lstrlen((LPCTSTR)lpszFunction)+40)*sizeof(TCHAR));
      StringCchPrintf((LPTSTR)lpDisplayBuf,
          LocalSize(lpDisplayBuf) / sizeof(TCHAR),
          TEXT("%s failed with error %d: %s"),
          lpszFunction, dw, lpMsgBuf);
      MessageBox(NULL, (LPCTSTR)lpDisplayBuf, TEXT("Error"), MB_OK);
 
      LocalFree(lpMsgBuf);
      LocalFree(lpDisplayBuf);
  }
 

用这个遍历目录  稍微改一下就可以用在程序里了


贴上某牛人的研究:

今天终于试验出FindFirstFile的正确用法

                                      

void CFindFilesDlg::OnBnClickedButton1()
{
 // TODO: 在此添加控件通知处理程序代码
 CString c1;
 CString stredit;
 CString strtemp;
 HANDLE hFile;
 WIN32_FIND_DATA fileinfo;
 DWORD errorcode = 0;
 m_Edit1.GetWindowText(c1);   //要熟悉控件的基本使用
 if(!c1.IsEmpty())
 {
       hFile=FindFirstFile("f:\\*.*",&fileinfo);
    while(hFile!=INVALID_HANDLE_VALUE&&errorcode!=ERROR_NO_MORE_FILES)
    {
     //
   strtemp=fileinfo.cFileName;
   stredit=stredit+"\r\n";
   stredit=stredit+strtemp;
   FindNextFile(hFile,&fileinfo);
   errorcode=GetLastError();
    }
    if(errorcode==ERROR_NO_MORE_FILES)
    {
     m_cedit1.SetWindowText(stredit);
     MessageBox("检索结束");
    }
    CloseHandle(hFile);
 }
}


在上述代码中

FindFirstFile第一个个参数需要一个路径,但要写*.*,表示从所有文件中找到的第一个.但写f:或者f:双斜杠都返回无效句柄.

如果f:\\1.txt 则对特定文件进行搜索,返回找到的第一个

找到的文件的文件结构被记录在WIN32_FIND_DATA结构体里

FindNextFile第一个参数是FindFirstFile的返回值,可以接着上次结果继续寻找

但注意!!!!

但一个目录的文件被搜索一遍后,FindNextFile返回的WIN32_FIND_DATA结构体将重复找到最后一个找到的文件,而不会终止.

让循环结束的方法就是找上一次的报错码,然后看有没有ERROR_NO_MORE_FILES信息发生.

hFile的有效与否个人觉得还是取决于第一次的FindFirstFile结果,本程序后半段的运行主要还是errorcode!=ERROR_NO_MORE_FILES在控制.
原创粉丝点击