代码之家  ›  专栏  ›  技术社区  ›  DShook

如何获取C++中目录中的文件列表?

  •  44
  • DShook  · 技术社区  · 17 年前

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

    13 回复  |  直到 8 年前
        1
  •  35
  •   Johannes Schaub - litb    17 年前

    标准C++不提供这样做的方法。但是 boost::filesystem 可以做到这一点: http://www.boost.org/doc/libs/1_37_0/libs/filesystem/example/simple_ls.cpp

        2
  •  58
  •   lahjaton_j    12 年前

    我用的是:

    /* 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
    
        3
  •  25
  •   Antonio    8 年前

    下面是Linux上C语言的一个例子。如果,你在Linux上,不介意用ANSIC做这么小的事情。

    #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);
    
        4
  •  4
  •   Yacoby    16 年前

    您必须使用操作系统调用(如win32 api)或它们周围的包装器。我倾向于使用 Boost.Filesystem 因为与mess(即win32 api)相比,它的界面更优越(同时也是跨平台的)。

    如果要使用win32 API,Microsoft有一个列表 of functions examples 在MSDN上。

        5
  •  3
  •   John Dibling    17 年前

    如果您在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);
    }
    
        6
  •  3
  •   AdrianEddy    8 年前

    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);
    }
    
        7
  •  2
  •   Roland Rabien    17 年前

    解决这个问题需要一个平台特定的解决方案。在UNIX/Linux上查找openddir()或在Windows上查找findfirstfile()。或者,有许多库可以为您处理平台特定的部分。

        8
  •  2
  •   Community Mohan Dere    9 年前

    我刚问过类似的问题 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
    
        9
  •  1
  •   Jean Knapp    8 年前

    在组合了许多片段之后,我终于找到了一个可重用的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");
    
        10
  •  0
  •   Community Mohan Dere    12 年前

    或者这样做,然后读取test.txt:

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

    “/b”表示只返回文件名,无进一步信息。

        11
  •  0
  •   Mat    12 年前
    HANDLE WINAPI FindFirstFile(
      __in   LPCTSTR lpFileName,
      __out  LPWIN32_FIND_DATA lpFindFileData
    );
    

    设置属性以仅查找目录。

        12
  •  0
  •   mystack    11 年前

    您可以使用以下代码获取目录中的所有文件。在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);
        }
    }
    
        13
  •  -1
  •   mmohab    12 年前
    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++;
     }