¿Cómo puedo obtener una lista de archivos en un directorio en C++?


¿Cómo se obtiene una lista de archivos dentro de un directorio para que cada uno pueda ser procesado?

Author: DShook, 2008-11-20

13 answers

El C++ estándar no proporciona una forma de hacer esto. Pero boost::filesystem puede hacer eso: http://www.boost.org/doc/libs/1_37_0/libs/filesystem/example/simple_ls.cpp

 35
Author: Johannes Schaub - litb,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-11-20 19:24:45

Esto es lo que uso:

/* 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
 58
Author: Andreas Bonini,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-11-18 11:19:59

Aquí hay un ejemplo en C en Linux. Eso es si, estás en Linux y no te importa hacer este pequeño bit en 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);
 26
Author: Chris Kloberdanz,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-10-05 17:58:33

Debe usar llamadas al sistema operativo (por ejemplo, la API Win32) o un envoltorio alrededor de ellas. Tiendo a usar Boost.Filesystem ya que es una interfaz superior en comparación con el lío que es la API Win32 (además de ser multiplataforma).

Si está buscando usar la API Win32, Microsoft tiene una lista de funciones y ejemplos en msdn.

 4
Author: Yacoby,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-12-19 12:56:05

Resolver esto requerirá una solución específica de la plataforma. Busque opendir () en unix/linux o FindFirstFile () en Windows. O bien, hay muchas bibliotecas que manejarán la parte específica de la plataforma para usted.

 2
Author: Roland Rabien,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-11-20 21:18:03

Si está en Windows y usando MSVC, la biblioteca MSDN tiene código de ejemplo que hace esto.

Y aquí está el código de ese enlace:

#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);
}
 2
Author: John Dibling,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-11-20 22:19:40

Acabo de hacer una pregunta similar y aquí está mi solución basada en la respuesta recibida (usando la biblioteca 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;
    }
}

La salida es como:

file1.txt
file2.dat
 2
Author: Bad,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 12:10:22

Versión de 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);
}
 1
Author: AdrianEddy,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-09-07 22:00:23

Después de combinar muchos fragmentos, finalmente encontré una solución reutilizable para Windows, que utiliza la biblioteca ATL, que viene con Visual Studio.

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

Para acceder al método, simplemente llame a:

getFiles("i:\\Folder1");
 1
Author: Jean Knapp,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-06-17 20:55:03

O haces esto y luego lees la prueba.txt:

#include <windows.h>

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

El "/b" significa que solo se devuelven los nombres de archivo, sin más información.

 0
Author: Enders,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-09-13 07:47:25
HANDLE WINAPI FindFirstFile(
  __in   LPCTSTR lpFileName,
  __out  LPWIN32_FIND_DATA lpFindFileData
);

Configure los atributos para que solo busquen directorios.

 0
Author: kenny,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-09-13 07:48:37

Puede usar el siguiente código para obtener todos los archivos en un directorio.Una simple modificación en la respuesta de Andreas Bonini para eliminar la ocurrencia de"." y ".."

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);
    }
}
 0
Author: tjdoubts,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-07-03 09:56:39
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
Author: sam,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-05-06 23:51:03