【问题标题】:How do I get a list of files in a directory in C++? [duplicate]如何在 C++ 中获取目录中的文件列表? [复制]
【发布时间】:2010-09-23 07:42:06
【问题描述】:

如何获取目录中的文件列表以便处理每个文件?

【问题讨论】:

    标签: c++ file directory


    【解决方案1】:

    但是boost::filesystem 可以做到这一点:http://www.boost.org/doc/libs/1_37_0/libs/filesystem/example/simple_ls.cpp

    【讨论】:

      【解决方案2】:

      在结合了很多sn-ps之后,终于找到了一个可复用的Windows解决方案,就是使用Visual Studio自带的ATL库。

      #include <atlstr.h>
      
      void getFiles(CString directory) {
          HANDLE dir;
          WIN32_FIND_DATA file_data;
          CString  file_name, full_file_name;
          if ((dir = FindFirstFile((directory + "/*"), &file_data)) == INVALID_HANDLE_VALUE)
          {
              // Invalid directory
          }
      
          while (FindNextFile(dir, &file_data)) {
              file_name = file_data.cFileName;
              full_file_name = directory + file_name;
              if (strcmp(file_data.cFileName, ".") != 0 && strcmp(file_data.cFileName, "..") != 0)
              {
                  std::string fileName = full_file_name.GetString();
                  // Do stuff with fileName
              }
          }
      }
      

      要访问该方法,只需调用:

      getFiles("i:\\Folder1");
      

      【讨论】:

      • 你能说一下这是适用于 Windows 还是 Linux 或两者兼而有之?
      • @NadavB 它使用 atlstr.h 库,我相信它仅适用于 Windows。
      【解决方案3】:

      这是 Linux 上的 C 语言示例。也就是说,如果您使用的是 Linux,并且不介意在 ANSI C 中做这些小事。

      #include <dirent.h>
      
      DIR *dpdf;
      struct dirent *epdf;
      
      dpdf = opendir("./");
      if (dpdf != NULL){
         while (epdf = readdir(dpdf)){
            printf("Filename: %s",epdf->d_name);
            // std::cout << epdf->d_name << std::endl;
         }
      }
      closedir(dpdf);
      

      【讨论】:

      • 事后别忘了closedir(dpdf)
      • 在这种情况下如何获取文件(文件类型)? epdf 是一个“dirent *”
      • 如果你正在制作一个库,则不能使用 dirent。
      • dpdfepdf 代表什么?
      • 当时我正在处理 PDF。这些名字可以是你喜欢的任何名字。
      【解决方案4】:

      C++11/Linux 版本:

      #include <dirent.h>
      
      if (auto dir = opendir("some_dir/")) {
          while (auto f = readdir(dir)) {
              if (!f->d_name || f->d_name[0] == '.')
                  continue; // Skip everything that starts with a dot
      
              printf("File: %s\n", f->d_name);
          }
          closedir(dir);
      }
      

      【讨论】:

        【解决方案5】:

        我刚刚问了一个类似的question,这是我根据收到的答案的解决方案(使用boost::filesystem 库):

        #include <string>
        #include <iostream>
        #include <boost/filesystem.hpp>
        using namespace std;
        using namespace boost::filesystem;
        
        int main()
        {
            path p("D:/AnyFolder");
            for (auto i = directory_iterator(p); i != directory_iterator(); i++)
            {
                if (!is_directory(i->path())) //we eliminate directories in a list
                {
                    cout << i->path().filename().string() << endl;
                }
                else
                    continue;
            }
        }
        

        输出如下:

        file1.txt
        file2.dat
        

        【讨论】:

          【解决方案6】:

          您可以使用以下代码获取目录中的所有文件。在 Andreas Bonini 答案中进行简单修改以删除“。”的出现。和“..”

          CString dirpath="d:\\mydir"
          DWORD errVal = ERROR_SUCCESS;
          HANDLE dir;
          WIN32_FIND_DATA file_data;
          CString  file_name,full_file_name;
          if ((dir = FindFirstFile((dirname+ "/*"), &file_data)) == INVALID_HANDLE_VALUE)
          {
              errVal=ERROR_INVALID_ACCEL_HANDLE;
              return errVal;
          }
          
          while (FindNextFile(dir, &file_data)) {
              file_name = file_data.cFileName;
              full_file_name = dirname+ file_name;
              if (strcmp(file_data.cFileName, ".") != 0 && strcmp(file_data.cFileName, "..") != 0)
              {
                  m_List.AddTail(full_file_name);
              }
          }
          

          【讨论】:

            【解决方案7】:
            void getFilesList(String filePath,String extension, vector<string> & returnFileName)
            {
                WIN32_FIND_DATA fileInfo;
                HANDLE hFind;   
                String  fullPath = filePath + extension;
                hFind = FindFirstFile(fullPath.c_str(), &fileInfo);
                if (hFind == INVALID_HANDLE_VALUE){return;} 
                else {
                    return FileName.push_back(filePath+fileInfo.cFileName);
                    while (FindNextFile(hFind, &fileInfo) != 0){
                        return FileName.push_back(filePath+fileInfo.cFileName);}
                    }
             }
            
            
             String optfileName ="";        
             String inputFolderPath =""; 
             String extension = "*.jpg*";
             getFilesList(inputFolderPath,extension,filesPaths);
             vector<string>::const_iterator it = filesPaths.begin();
             while( it != filesPaths.end())
             {
                frame = imread(*it);//read file names
                        //doyourwork here ( frame );
                sprintf(buf, "%s/Out/%d.jpg", optfileName.c_str(),it->c_str());
                imwrite(buf,frame);   
                it++;
             }
            

            【讨论】:

            • getFilesList方法中有2个return,return FileName.push_back(filePath+fileInfo.cFileName);后面的代码无法访问
            【解决方案8】:

            这是我使用的:

            /* Returns a list of files in a directory (except the ones that begin with a dot) */
            
            void GetFilesInDirectory(std::vector<string> &out, const string &directory)
            {
            #ifdef WINDOWS
                HANDLE dir;
                WIN32_FIND_DATA file_data;
            
                if ((dir = FindFirstFile((directory + "/*").c_str(), &file_data)) == INVALID_HANDLE_VALUE)
                    return; /* No files found */
            
                do {
                    const string file_name = file_data.cFileName;
                    const string full_file_name = directory + "/" + file_name;
                    const bool is_directory = (file_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0;
            
                    if (file_name[0] == '.')
                        continue;
            
                    if (is_directory)
                        continue;
            
                    out.push_back(full_file_name);
                } while (FindNextFile(dir, &file_data));
            
                FindClose(dir);
            #else
                DIR *dir;
                class dirent *ent;
                class stat st;
            
                dir = opendir(directory);
                while ((ent = readdir(dir)) != NULL) {
                    const string file_name = ent->d_name;
                    const string full_file_name = directory + "/" + file_name;
            
                    if (file_name[0] == '.')
                        continue;
            
                    if (stat(full_file_name.c_str(), &st) == -1)
                        continue;
            
                    const bool is_directory = (st.st_mode & S_IFDIR) != 0;
            
                    if (is_directory)
                        continue;
            
                    out.push_back(full_file_name);
                }
                closedir(dir);
            #endif
            } // GetFilesInDirectory
            

            【讨论】:

            • Windows 代码在启用 Unicode 的情况下编译时无法正常工作。我通过显式调用附加了“A”的 ASCII 函数来解决这个问题。具体来说,使用 WIN32_FIND_DATAA、FindFirstFileA 和 FindNextFileA 一切正常。显然这是一个黑客,但我住在一个说英语的国家,所以它对我有用。 :0 感谢示例代码!
            • 如果你正在制作一个库,则不能使用 dirent。
            • @tuple_cat &lt;dirent.h&gt;, &lt;sys/stat.h&gt; 以及肯定包含std::string 的某种文件。使用std::string,你必须把std::放在string类型声明的前面并使用opendir(directory.c_str())
            【解决方案9】:
            HANDLE WINAPI FindFirstFile(
              __in   LPCTSTR lpFileName,
              __out  LPWIN32_FIND_DATA lpFindFileData
            );
            

            将属性设置为仅查找目录。

            【讨论】:

              【解决方案10】:

              或者你这样做然后读出test.txt:

              #include <windows.h>
              
              int main() {    
              system("dir /b > test.txt");
              }
              

              “/b”表示只返回文件名,没有更多信息。

              【讨论】:

              • 这看起来非常好用且简单,但我不知道如何使用它。您能否解释一下/b 是什么以及我们将在哪里提供目录?
              【解决方案11】:

              您必须使用操作系统调用(例如 Win32 API)或围绕它们的包装器。我倾向于使用Boost.Filesystem,因为与 Win32 API 的混乱(以及跨平台)相比,它具有更好的接口。

              如果您希望使用 Win32 API,Microsoft 在 msdn 上有一个列表 of functionsexamples

              【讨论】:

                【解决方案12】:

                如果您在 Windows 中并使用 MSVC,则 MSDN 库有 sample code that does this.

                这是来自该链接的代码:

                #include <windows.h>
                #include <tchar.h> 
                #include <stdio.h>
                #include <strsafe.h>
                
                void ErrorHandler(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 2 is not longer than MAX_PATH.
                
                   StringCchLength(argv[1], MAX_PATH, &length_of_arg);
                
                   if (length_of_arg > (MAX_PATH - 2))
                   {
                      _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) 
                   {
                      ErrorHandler(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) 
                   {
                      ErrorHandler(TEXT("FindFirstFile"));
                   }
                
                   FindClose(hFind);
                   return dwError;
                }
                
                
                void ErrorHandler(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 exit the process
                
                    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);
                }
                

                【讨论】:

                  【解决方案13】:

                  解决此问题需要特定于平台的解决方案。在 unix/linux 上查找 opendir() 或在 Windows 上查找 FindFirstFile()。或者,有许多库会为您处理特定于平台的部分。

                  【讨论】:

                    猜你喜欢
                    • 2012-04-22
                    • 2010-09-17
                    • 1970-01-01
                    • 2020-05-04
                    • 2020-09-11
                    相关资源
                    最近更新 更多