Comment lister le contenu d'un répertoire en C++ sous Microsoft Windows

Il arrive qu'on souhaite lister le contenu d'un répertoire sous Microsoft Windows. Ce système d'exploitation offre une interface de type client/ serveur pas si mal pour y arriver.

Nous aurons recours à quelques fichiers d'en-tête usuels.

Nous utiliserons les flux et les chaînes dans leur forme basée sur des caractères étendus, du fait que depuis Visual Studio 2005 la macro UNICODE est définie par défaut et fait en sorte que les versions à caractères étendus des fonctions de l'API Win32 sont celles qui seront invoquées.

#include <iostream>
#include <windows.h> // évidemment
#include <algorithm>
#include <string>
#include <utility>
#include <vector>
using namespace std;

Nous serons préoccupés par les fichiers et les répertoires. Une simple énumération fera le travail.

enum Categorie { Fichier, Repertoire };
wostream& operator<<(wostream &os, Categorie c)
{
   return os << ((c == Fichier)? L"Fichier" : L"Repertoire");
}

Notre fonction retournera une liste de paires faites d'un nom et d'une catégorie. Les exceptions possibles correspondent aux cas d'erreurs soulignés par les fonctions de l'API de la plateforme.

class RepertoireTropPlein {};
class RepertoireVide {};
vector<pair<wstring, Categorie>>
   ObtenirContenuRepertoireCourant();

Le programme principal sera tout simple : il obtiendra puis affichera la liste des éléments du répertoire courant.

int main()
{
   try
   {
      auto v = ObtenirContenuRepertoireCourant();
      for(const auto &p : v)
         wcout << p.second << L": " << p.first << std::endl;
   }
   catch (RepertoireTropPlein)
   {
      wcerr << L"Le répertoire courant est trop plein" << endl;
   }
   catch (RepertoireVide)
   {
      wcerr << L"Le répertoire courant est vide" << endl;
   }
}

Une petite fonction retournera le nom du répertoire courant.

Les macros MAX_PATH et ERROR_INSUFFICIENT_BUFFER proviennent de <windows.h>.

Voir aussi les fonctions SetCurrentDirectory(), pour changer de répertoire, de même que CreateDirectory() et RemoveDirectory() pour créer et supprimer un répertoire.

wstring NomRepertoireCourant()
{
   const int CAPACITE = MAX_PATH;
   wchar_t nom[CAPACITE];
   int n = GetCurrentDirectory(CAPACITE, nom);
   if ((n == ERROR_INSUFFICIENT_BUFFER)
      throw RepertoireTropPlein{};
   return wstring(nom + 0, nom + n);
}

La fonction retournant la liste des éléments du répertoire obtiendra ces éléments un par un.

Les fonctions importantes sont indiquées en caractères gras.

vector<pair<wstring, Categorie>> ObtenirContenuRepertoireCourant()
{
   auto nom = NomRepertoireCourant();
   // pour les curieuses et les curieux
   wcout << "Répertoire courant: " << nom << endl;
   if (nom[nom.size() - 1] != L'\\')
      nom += L'\\';
   nom += L"*.*";

   HANDLE hList;
   WIN32_FIND_DATA FileData;
   if ((hList = FindFirstFile(NomRep.c_str(), &FileData)) == INVALID_HANDLE_VALUE)
      throw RepertoireVide{};

   vector<pair<wstring, Categorie>> v;
   bool fini;
   do
   {
      // Un répertoire?
      if (FileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
         v.emplace_back(FileData.cFileName, Repertoire);
      else
         v.emplace_back(FileData.cFileName, Fichier);
      fini = (!FindNextFile(hList, &FileData) &&
              GetLastError() == ERROR_NO_MORE_FILES);
   }
   while (!fini);
   FindClose(hList);
   return v;
}

Pas plus compliqué que ça.


Valid XHTML 1.0 Transitional

CSS Valide !