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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/306533/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-27 14:29:11  来源:igfitidea点击:

How do I get a list of files in a directory in C++?

c++filedirectory

提问by DShook

How do you get a list of files within a directory so each can be processed?

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

采纳答案by Johannes Schaub - litb

回答by Thomas Bonini

Here's what I use:

这是我使用的:

/* 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

回答by Chris Kloberdanz

Here's an example in C on Linux. That's if, you're on Linux and don't mind doing this small bit in ANSI C.

这是 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);

回答by AdrianEddy

C++11/Linux version:

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);
}

回答by Yacoby

You have to use operating system calls (e.g. the Win32 API) or a wrapper around them. I tend to use Boost.Filesystemas it is superior interface compared to the mess that is the Win32 API (as well as being cross platform).

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

If you are looking to use the Win32 API, Microsoft has a list of functionsand exampleson msdn.

如果您希望使用 Win32 API,Microsoft在 msdn 上有一个函数示例列表。

回答by Bad

I've just asked a similar questionand here's my solution based on answer received (using boost::filesystemlibrary):

我刚刚问了一个类似的问题,这是我基于收到的答案(使用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;
    }
}

Output is like:

输出是这样的:

file1.txt
file2.dat

回答by John Dibling

If you're in Windows & using MSVC, the MSDN library has sample code that does this.

如果您使用的是 Windows 并使用 MSVC,则 MSDN 库具有执行此操作的示例代码。

And here's the code from that link:

这是该链接中的代码:

#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);
}

回答by Roland Rabien

Solving this will require a platform specific solution. Look for opendir() on unix/linux or FindFirstFile() on Windows. Or, there are many libraries that will handle the platform specific part for you.

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

回答by Jean Knapp

After combining a lot of snippets, I finally found a reuseable solution for Windows, that uses ATL Library, which comes with Visual Studio.

在结合了很多片段之后,我终于找到了一个可重用的 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
        }
    }
}

To access the method, just call:

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

getFiles("i:\Folder1");

回答by tjdoubts

You can use the following code for getting all files in a directory.A simple modification in the Andreas Bonini answer to remove the occurance of "." and ".."

您可以使用以下代码获取目录中的所有文件。 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);
    }
}