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

时间:2022-08-25 23:22:57

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

如何在一个目录中获取文件列表,这样每个文件都可以被处理?

13 个解决方案

#1


34  

Standard C++ doesn't provide a way to do this. But boost::filesystem can do that: http://www.boost.org/doc/libs/1_37_0/libs/filesystem/example/simple_ls.cpp

标准c++没有提供这样做的方法。但是boost::文件系统可以做到这一点:http://www.boost.org/doc/libs/1 _37_ 0/libs/文件系统/示例/simple_ls.cpp。

#2


57  

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

#3


26  

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

#4


4  

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

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

If you are looking to use the Win32 API, Microsoft has a list of functions and examples on msdn.

如果您想要使用Win32 API,微软有一个msdn上的功能列表和示例。

#5


2  

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()。或者,有许多库可以为您处理平台特定的部分。

#6


2  

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

#7


2  

I've just asked a similar question and here's my solution based on answer received (using boost::filesystem library):

我刚刚问了一个类似的问题,这是我基于收到的答案的解决方案(使用boost::文件系统库):

#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

#8


1  

After combining a lot of snippets, I finally found out one that doesn't bring errors, will accept a std::string argument and is reusable.

在结合了许多代码片段之后,我终于发现了一个不会带来错误的代码,它将接受std::string参数,并且是可重用的。

#include <atlstr.h>

void getFiles(CString directory) {
    Console console;
    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");

#9


1  

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

#10


0  

Or you do this and then read out the test.txt:

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

#include <windows.h>

int main() {    
system("dir /b > test.txt");
}

The "/b" means just filenames are returned, no further info.

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

#11


0  

HANDLE WINAPI FindFirstFile(
  __in   LPCTSTR lpFileName,
  __out  LPWIN32_FIND_DATA lpFindFileData
);

Setup the attributes to only look for directories.

设置属性以查找目录。

#12


0  

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 ".."

您可以使用下面的代码来获取目录中的所有文件。安德里亚斯·伯尼尼的一个简单的修改,消除了“。”和“..”的出现。

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  

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

#1


34  

Standard C++ doesn't provide a way to do this. But boost::filesystem can do that: http://www.boost.org/doc/libs/1_37_0/libs/filesystem/example/simple_ls.cpp

标准c++没有提供这样做的方法。但是boost::文件系统可以做到这一点:http://www.boost.org/doc/libs/1 _37_ 0/libs/文件系统/示例/simple_ls.cpp。

#2


57  

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

#3


26  

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

#4


4  

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

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

If you are looking to use the Win32 API, Microsoft has a list of functions and examples on msdn.

如果您想要使用Win32 API,微软有一个msdn上的功能列表和示例。

#5


2  

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()。或者,有许多库可以为您处理平台特定的部分。

#6


2  

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

#7


2  

I've just asked a similar question and here's my solution based on answer received (using boost::filesystem library):

我刚刚问了一个类似的问题,这是我基于收到的答案的解决方案(使用boost::文件系统库):

#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

#8


1  

After combining a lot of snippets, I finally found out one that doesn't bring errors, will accept a std::string argument and is reusable.

在结合了许多代码片段之后,我终于发现了一个不会带来错误的代码,它将接受std::string参数,并且是可重用的。

#include <atlstr.h>

void getFiles(CString directory) {
    Console console;
    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");

#9


1  

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

#10


0  

Or you do this and then read out the test.txt:

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

#include <windows.h>

int main() {    
system("dir /b > test.txt");
}

The "/b" means just filenames are returned, no further info.

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

#11


0  

HANDLE WINAPI FindFirstFile(
  __in   LPCTSTR lpFileName,
  __out  LPWIN32_FIND_DATA lpFindFileData
);

Setup the attributes to only look for directories.

设置属性以查找目录。

#12


0  

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 ".."

您可以使用下面的代码来获取目录中的所有文件。安德里亚斯·伯尼尼的一个简单的修改,消除了“。”和“..”的出现。

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  

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