API Windows / Gestion de fichiers
Résolu/Fermé
A voir également:
- API Windows / Gestion de fichiers
- Clé windows 10 gratuit - Guide
- Windows 12 - Accueil - Windows
- Montage video windows - Guide
- Windows ne démarre pas - Guide
- Windows 10 gratuit - Accueil - Mise à jour
12 réponses
[Dal]
Messages postés
6194
Date d'inscription
mercredi 15 septembre 2004
Statut
Contributeur
Dernière intervention
11 octobre 2024
1 092
26 avril 2021 à 10:14
26 avril 2021 à 10:14
Salut Telnaz,
L'API Windows comporte la fonction FindFirstFile() qui permet de retourner le premier fichier matchant l'argument de recherche et FindNextFile() qui permet de retourner le reste.
https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-findfirstfilea
https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-findnextfilea
https://docs.microsoft.com/en-us/windows/win32/fileio/listing-the-files-in-a-directory
Dal
L'API Windows comporte la fonction FindFirstFile() qui permet de retourner le premier fichier matchant l'argument de recherche et FindNextFile() qui permet de retourner le reste.
https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-findfirstfilea
https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-findnextfilea
https://docs.microsoft.com/en-us/windows/win32/fileio/listing-the-files-in-a-directory
Dal
Salut, merci pour ta réponse.
En effet, j'ai déjà utilisé ces fonctions ... D'ailleurs, j'arrive bien à lister les fichiers et sous-dossier du dossier courant. Par contre, je ne sais pas comment effectuer cette analyse de façon récursive, c'est-à-dire également lister tous les fichiers, compris dans les sous-dossiers ...
bufferCheminSousDossier : chemin absolu du dossier courant (ou j'effectue la recherche de fichiers)
Voici mon code :
En effet, j'ai déjà utilisé ces fonctions ... D'ailleurs, j'arrive bien à lister les fichiers et sous-dossier du dossier courant. Par contre, je ne sais pas comment effectuer cette analyse de façon récursive, c'est-à-dire également lister tous les fichiers, compris dans les sous-dossiers ...
bufferCheminSousDossier : chemin absolu du dossier courant (ou j'effectue la recherche de fichiers)
Voici mon code :
//hedit sont les formulaires remplis si les boutons correspondants sont actionnés
if (hEditJ !=0 && hEditI !=0)
{
strcat(bufferCheminSousDossier,"\\*");
hFind2 = FindFirstFile(bufferCheminSousDossier, &ffd);
if (INVALID_HANDLE_VALUE == hFind2)
{
DisplayErrorBox(TEXT("FindFirstFile"));
return dwError;
}
do {
if (ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
{
Trouve =1;
MessageBox(NULL, ffd.cFileName , "test", MB_ICONWARNING | MB_OK);
}
else
{
filesize.LowPart = ffd.nFileSizeLow;
filesize.HighPart = ffd.nFileSizeHigh;
MessageBox(NULL, ffd.cFileName , "test", MB_ICONWARNING | MB_OK);
SendMessage(hEditK, WM_SETTEXT, 0, (long)filesize.QuadPart);
}
} while (FindNextFile(hFind2, &ffd) !=0);
if (Trouve == 0)
{
MessageBox(NULL, "Il n'existe aucun fichier qui correspond à la demande", "Erreur", MB_ICONWARNING | MB_OK);
}
dwError = GetLastError();
if (dwError != ERROR_NO_MORE_FILES)
{
DisplayErrorBox(TEXT("FindFirstFile"));
msgboxID = MessageBox(NULL, "Erreur", "Erreur", MB_ICONWARNING | MB_OK);
}
FindClose(hFind);
return dwError;
}
[Dal]
Messages postés
6194
Date d'inscription
mercredi 15 septembre 2004
Statut
Contributeur
Dernière intervention
11 octobre 2024
1 092
26 avril 2021 à 14:31
26 avril 2021 à 14:31
Tu peux t'inspirer de ce code :
https://stackoverflow.com/questions/2038912/how-to-recursively-traverse-directories-in-c-on-windows/2043959#2043959
https://stackoverflow.com/questions/2038912/how-to-recursively-traverse-directories-in-c-on-windows/2043959#2043959
J'ai repris ce même code, cela me fait pareil ... il n'y a pas de procédure récursive :
main.c :
fonction.c :
main.c :
// Code présent au-dessus
if (hEditJ !=0 && hEditI !=0)
{
FindFilesRecursively(_T(bufferCheminSousDossier), _T("*."));
}
// ..........
fonction.c :
HANDLE hFind3 = INVALID_HANDLE_VALUE;
TCHAR szFullPattern[MAX_PATH];
void FindFilesRecursively(LPCTSTR lpFolder, LPCTSTR lpFilePattern)
{
PathCombine(szFullPattern, lpFolder, _T("*"));
hFind3= FindFirstFile(szFullPattern, &ffd);
if(hFind3 != INVALID_HANDLE_VALUE)
{
do
{
if(ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
{
PathCombine(szFullPattern, lpFolder, ffd.cFileName);
FindFilesRecursively(szFullPattern, lpFilePattern);
}
} while(FindNextFile(hFind3, &ffd));
FindClose(hFind3);
}
PathCombine(szFullPattern, lpFolder, lpFilePattern);
hFind3 = FindFirstFile(szFullPattern, &ffd);
if(hFind3 != INVALID_HANDLE_VALUE)
{
do
{
if(!(ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
{
PathCombine(szFullPattern, lpFolder, ffd.cFileName);
MessageBox(NULL, szFullPattern , "Liste", MB_OK);
}
} while(FindNextFile(hFind3, &ffd));
FindClose(hFind3);
}
}
Vous n’avez pas trouvé la réponse que vous recherchez ?
Posez votre question
Phil_1857
Messages postés
1872
Date d'inscription
lundi 23 mars 2020
Statut
Membre
Dernière intervention
28 février 2024
168
Modifié le 27 avril 2021 à 10:33
Modifié le 27 avril 2021 à 10:33
Bonjour Telnaz,
Et comme ça ? (scan_dir s'appelle elle-même recursivement) :
Et comme ça ? (scan_dir s'appelle elle-même recursivement) :
#include <windows.h> void scan_dir(char *path) { WIN32_FIND_DATA fd; void *dir; char newp[80], search_path[80], *filename; strlwr(path); strcpy(search_path, path); strcat(search_path, "*.*"); dir = FindFirstFile(search_path, &fd); // . DOS FindNextFile(dir, &fd); // .. DOS while(FindNextFile(dir, &fd)) { if((fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0) // file { filename = fd.cFileName; } else //directory { strcpy(newp, path); strcat(newp, fd.cFileName); strcat(newp, "\\"); scan_dir(newp); } } FindClose(dir); }
Non cela fonctionne mal avec mon code, j'ai beaucoup d'erreur ...
Pour revenir au code précédent, j'ai remarqué que le valeur du szFullPattern, lorsque l'on cherche les fichiers correspondants, ne changeait pas. C'est-à-dire, il ne suit pas la procédure récursive qui est faite lors de la recherche des dossiers ...
Je pense donc qu'il manque une boucle à ce niveau là ... Mais je n'ai pas réussi à améliorer la chose
Pour revenir au code précédent, j'ai remarqué que le valeur du szFullPattern, lorsque l'on cherche les fichiers correspondants, ne changeait pas. C'est-à-dire, il ne suit pas la procédure récursive qui est faite lors de la recherche des dossiers ...
Je pense donc qu'il manque une boucle à ce niveau là ... Mais je n'ai pas réussi à améliorer la chose
Phil_1857
Messages postés
1872
Date d'inscription
lundi 23 mars 2020
Statut
Membre
Dernière intervention
28 février 2024
168
Modifié le 27 avril 2021 à 13:18
Modifié le 27 avril 2021 à 13:18
Ah OK,
Je proposais cette fonction récursive car je m'en servais souvent dans divers projets pour explorer une arborescence de répertoires (en profondeur d'abord) et elle fonctionnait très bien
Evidemment, j'ai simplifié, dans le if où on détecte que c'est un fichier, je faisais quelque chose de filename ......
J'y avais même inclus les fonctions setjump() et longjump() pour re sauter à mon programme principal dès que j'avais trouvé le fichier recherché, et éviter tous les dépilages des appels successifs de la fonction
Je proposais cette fonction récursive car je m'en servais souvent dans divers projets pour explorer une arborescence de répertoires (en profondeur d'abord) et elle fonctionnait très bien
Evidemment, j'ai simplifié, dans le if où on détecte que c'est un fichier, je faisais quelque chose de filename ......
J'y avais même inclus les fonctions setjump() et longjump() pour re sauter à mon programme principal dès que j'avais trouvé le fichier recherché, et éviter tous les dépilages des appels successifs de la fonction
J'ai corrigé les nombreux soucis de compatibilité ...
Mais, après compilation et lancement de l'interface, je n'ai rien qui est renvoyé lors de l'exécution de la fonction.
J'ai, un doute, quand j'appelle la fonction dans le main.c, j'écris :
scan_dir(bufferCheminSousDossier);
?
bufferCheminSousDossier est le chemin absolu du sous dossier que je dois analyser
Mais, après compilation et lancement de l'interface, je n'ai rien qui est renvoyé lors de l'exécution de la fonction.
J'ai, un doute, quand j'appelle la fonction dans le main.c, j'écris :
scan_dir(bufferCheminSousDossier);
?
bufferCheminSousDossier est le chemin absolu du sous dossier que je dois analyser
Phil_1857
Messages postés
1872
Date d'inscription
lundi 23 mars 2020
Statut
Membre
Dernière intervention
28 février 2024
168
Modifié le 27 avril 2021 à 13:52
Modifié le 27 avril 2021 à 13:52
Comme je te l'expliquais, j'ai simplifié pour montrer la structure, donc il ne se passe pas grand chose si tu à copié ma fonction telle quelle
Par exemple, dans un projet, je stockais le nom du fichier trouvé dans un fichier texte:
l'appel était comme ceci:
Par exemple, dans un projet, je stockais le nom du fichier trouvé dans un fichier texte:
if((fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0) // file { ................ fprintf(fp, "%s%s\n",path, filename); } else { //répertoire ........ }
l'appel était comme ceci:
scan_dir('C:\\phil\\resultat\\');
Phil_1857
Messages postés
1872
Date d'inscription
lundi 23 mars 2020
Statut
Membre
Dernière intervention
28 février 2024
168
27 avril 2021 à 13:58
27 avril 2021 à 13:58
C'est
et non pas
filename = fd.cFileName;
et non pas
filename = ffd.cFileName;
Phil_1857
Messages postés
1872
Date d'inscription
lundi 23 mars 2020
Statut
Membre
Dernière intervention
28 février 2024
168
27 avril 2021 à 14:04
27 avril 2021 à 14:04
ok, mais dans le test if tu as écris:
avec fd
if((fd.dwFileAttributes ....
avec fd
Phil_1857
Messages postés
1872
Date d'inscription
lundi 23 mars 2020
Statut
Membre
Dernière intervention
28 février 2024
168
Modifié le 27 avril 2021 à 16:43
Modifié le 27 avril 2021 à 16:43
ah!
attend voir, ce ne serait pas plutôt:
avec double quotes
(je suis en train de faire du Python, et là c'est la même chose, mais pas en C)
attend voir, ce ne serait pas plutôt:
scan_dir("D:\\MA_atp\\");
avec double quotes
(je suis en train de faire du Python, et là c'est la même chose, mais pas en C)
Phil_1857
Messages postés
1872
Date d'inscription
lundi 23 mars 2020
Statut
Membre
Dernière intervention
28 février 2024
168
Modifié le 27 avril 2021 à 17:05
Modifié le 27 avril 2021 à 17:05
ok, mais tu as bien mis des double quotes pour re tester ??
too many characters in character constant
ça venait bien de l'emploi de simple quotes
Sinon, bizarre .... si il n'entre pas dans la boucle, c'est que FindNextFile(dir, &fd) renvoi false, donc qu'il ne trouve
rien comme fichiers ou répertoires dans dir
too many characters in character constant
ça venait bien de l'emploi de simple quotes
Sinon, bizarre .... si il n'entre pas dans la boucle, c'est que FindNextFile(dir, &fd) renvoi false, donc qu'il ne trouve
rien comme fichiers ou répertoires dans dir
Oui oui ne t'inquiète pas ... désolé j'oublie de tout te préciser mais c'est que j'ai fais pas mal de changements...
Aux dernières nouvelles, j'essaie de comprendre pourquoi il n'analyse pas les fichiers...
J'ai vérifié que la variable path comprenait bien le chemin, mais ensuite ça n'a pas l'air de fonctionner
Aux dernières nouvelles, j'essaie de comprendre pourquoi il n'analyse pas les fichiers...
J'ai vérifié que la variable path comprenait bien le chemin, mais ensuite ça n'a pas l'air de fonctionner
[Dal]
Messages postés
6194
Date d'inscription
mercredi 15 septembre 2004
Statut
Contributeur
Dernière intervention
11 octobre 2024
1 092
28 avril 2021 à 01:24
28 avril 2021 à 01:24
Salut Telnaz,
Je suis sous Linux habituellement, alors il m'est difficile de tester les codes Win32.
Le code posté sur SO boucle sur le même répertoire racine et j'ai la flemme de le déboguer tellement il comporte de code à la sauce MS.
Alors en voilà un autre, qui est fortement inspiré de celui posté dans ce fil https://arstechnica.com/civis/viewtopic.php?t=817827 par earl.
Ce code parcourt bien les répertoires. Il évite les entrées "." qui correspondent au répertoire courant et ".." qui correspond au répertoire parent et chez moi, il liste bien les 58 Fichiers contenus dans 26 Dossiers situés dans un répertoire qui se trouve à la racine de C:\ et qui s'appelle "Drivers".
Dal
Je suis sous Linux habituellement, alors il m'est difficile de tester les codes Win32.
Le code posté sur SO boucle sur le même répertoire racine et j'ai la flemme de le déboguer tellement il comporte de code à la sauce MS.
Alors en voilà un autre, qui est fortement inspiré de celui posté dans ce fil https://arstechnica.com/civis/viewtopic.php?t=817827 par earl.
#include <stdio.h> #include <windows.h> void recursively_list_files(char * dir) { HANDLE hFind; WIN32_FIND_DATA fd; char path[MAX_PATH + 1]; sprintf(path, "%s\\*", dir); printf("---- dans le repertoire %s ----\n\n", dir); if ((hFind = FindFirstFile(path, &fd)) == INVALID_HANDLE_VALUE) { printf("Erreur FindFirstFIle sur %s\n", path); exit(1); } while(1) { if ((strcmp(".", fd.cFileName) !=0) && (strcmp("..", fd.cFileName) != 0)) { if (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { /* c'est un dossier */ sprintf(path, "%s\\%s", dir, fd.cFileName); recursively_list_files(path); } else { /* c'est un fichier */ printf("fichier : %s\n", fd.cFileName); } } if (!FindNextFile(hFind, &fd)) break; } if (GetLastError() != ERROR_NO_MORE_FILES) { printf("Erreur FindNextFile - dans %s\n", path); exit(1); } if (FindClose(hFind) == FALSE) { printf("Erreur FindClose\n"); exit(1); } } int main(void) { /* sur mon disque C: j'ai un répertoire Drivers avec 58 Fichiers dans 26 Dossiers */ recursively_list_files("C:\\Drivers"); return 0; }
Ce code parcourt bien les répertoires. Il évite les entrées "." qui correspondent au répertoire courant et ".." qui correspond au répertoire parent et chez moi, il liste bien les 58 Fichiers contenus dans 26 Dossiers situés dans un répertoire qui se trouve à la racine de C:\ et qui s'appelle "Drivers".
---- dans le repertoire C:\Drivers ---- ---- dans le repertoire C:\Drivers\input ---- ---- dans le repertoire C:\Drivers\input\9FT4R ---- ---- dans le repertoire C:\Drivers\input\9FT4R\Bin ---- ---- dans le repertoire C:\Drivers\input\9FT4R\Bin\production ---- ---- dans le repertoire C:\Drivers\input\9FT4R\Bin\production\Windows10-x64 ---- fichier : HidEventFilter.cat fichier : HidEventFilter.inf fichier : HidEventFilter.sys ---- dans le repertoire C:\Drivers\network ---- ---- dans le repertoire C:\Drivers\network\6YDJP ---- ---- dans le repertoire C:\Drivers\network\6YDJP\Windows ---- ---- dans le repertoire C:\Drivers\network\6YDJP\Windows\WIN10 ---- ---- dans le repertoire C:\Drivers\network\6YDJP\Windows\WIN10\32 ---- fichier : rtux86w10.cat fichier : rtux86w10.INF fichier : rtux86w10.sys ---- dans le repertoire C:\Drivers\network\6YDJP\Windows\WIN10\64 ---- fichier : rtux64w10.cat fichier : rtux64w10.INF fichier : rtux64w10.sys ---- dans le repertoire C:\Drivers\storage ---- ---- dans le repertoire C:\Drivers\storage\1NN1D ---- ---- dans le repertoire C:\Drivers\storage\1NN1D\Drivers ---- ---- dans le repertoire C:\Drivers\storage\1NN1D\Drivers\Production ---- ---- dans le repertoire C:\Drivers\storage\1NN1D\Drivers\Production\Windows10-x64 ---- fichier : dpinst.exe fichier : HfcDisableService.exe fichier : iaAHCIC.cat fichier : iaAHCIC.inf fichier : iaStorAC.cat fichier : iaStorAC.inf fichier : iaStorAC.sys fichier : iaStorAfs.sys fichier : iaStorAfsNative.exe fichier : iaStorAfsService.exe fichier : iaStorSW.cat fichier : iaStorSW.inf fichier : iaStorSwExt.cat fichier : iaStorSwExt.inf fichier : Optane.dll fichier : RstMwService.exe fichier : ShellPackage.msi ---- dans le repertoire C:\Drivers\storage\M31NN ---- ---- dans le repertoire C:\Drivers\storage\M31NN\Drivers ---- ---- dans le repertoire C:\Drivers\storage\M31NN\Drivers\x64 ---- fichier : iaLPSS2_GPIO2.sys fichier : ialpss2_gpio2_cnl.cat fichier : iaLPSS2_GPIO2_CNL.inf fichier : iaLPSS2_I2C.sys fichier : ialpss2_i2c_cnl.cat fichier : iaLPSS2_I2C_CNL.inf fichier : iaLPSS2_SPI.sys fichier : ialpss2_spi_cnl.cat fichier : iaLPSS2_SPI_CNL.inf fichier : iaLPSS2_UART2.sys fichier : ialpss2_uart2_cnl.cat fichier : iaLPSS2_UART2_CNL.inf ---- dans le repertoire C:\Drivers\storage\R16KJ ---- ---- dans le repertoire C:\Drivers\storage\R16KJ\Install ---- ---- dans le repertoire C:\Drivers\storage\R16KJ\Install\DrvBin64 ---- ---- dans le repertoire C:\Drivers\storage\R16KJ\Install\DrvBin64\ExtInf ---- fichier : RtsCrExt.inf fichier : rtscrext64.cat fichier : SDRTCPRM.dll fichier : RsCRIcon.dll fichier : RtsPer.sys fichier : rtsper64.cat fichier : RtsperDLnQS.inf ---- dans le repertoire C:\Drivers\storage\TBT51 ---- ---- dans le repertoire C:\Drivers\storage\TBT51\production ---- ---- dans le repertoire C:\Drivers\storage\TBT51\production\Windows10-x64 ---- fichier : TbtBusDrv.sys fichier : TbtControlCenterToastLauncher.exe fichier : TbtFilterDrv.dll fichier : tbthostcontroller.cat fichier : TbtHostController.inf fichier : tbthostcontrollerextension.cat fichier : TbtHostControllerExtension.inf fichier : tbthostcontrollerhsacomponent.cat fichier : TbtHostControllerHsaComponent.inf fichier : tbtp2pndisdrv.cat fichier : TbtP2pNdisDrv.inf fichier : TbtP2pNdisDrv.sys fichier : ThunderboltService.exe
Dal
Cela fonctionne très bien, merci beaucoup. Il me reste tout de même un problème d'affichage à régler.
Je n'ai pas de console, uniquement une interface graphique ... Pour vérifier si cela fonctionnait, j'ai ajouté un "MessageBox" pour bien afficher tous les fichiers trouvés.
Cependant, l'objectif est de lister les dossiers et fichiers comme tu l'as montré.
J'ai ajouté ceci :
Cependant, lors de l’exécution, je n'ai pas tous les fichiers d'afficher, seulement quelques uns et le "dans le repertoire " n'est affiché qu'une seule fois ...
PS : je n'ai pas utilisé la fonction main(void), j'ai directement écris recursively_list_files(chemin); dans une boucle if dans mon main.c
Je n'ai pas de console, uniquement une interface graphique ... Pour vérifier si cela fonctionnait, j'ai ajouté un "MessageBox" pour bien afficher tous les fichiers trouvés.
Cependant, l'objectif est de lister les dossiers et fichiers comme tu l'as montré.
J'ai ajouté ceci :
... char path[MAX_PATH +1] FILE* fichier; fichier = fopen("donnees.txt", "w+"); sprintf(path, "%s\\*", dir); fprintf(fichier, "---- dans le repertoire %s ----\n\n", dir); if .... } else { /* c'est un fichier */ fprintf(fichier, "fichier : %s\n", fd.cFileName); .... fclose(fichier); }
Cependant, lors de l’exécution, je n'ai pas tous les fichiers d'afficher, seulement quelques uns et le "dans le repertoire " n'est affiché qu'une seule fois ...
PS : je n'ai pas utilisé la fonction main(void), j'ai directement écris recursively_list_files(chemin); dans une boucle if dans mon main.c
[Dal]
Messages postés
6194
Date d'inscription
mercredi 15 septembre 2004
Statut
Contributeur
Dernière intervention
11 octobre 2024
1 092
>
Telnaz
Modifié le 28 avril 2021 à 12:30
Modifié le 28 avril 2021 à 12:30
Comme la fonction est appelée récursivement, à chaque lancement de la fonction, tu crées un nouveau fichier donnees.txt qui écrase l'ancien (et qui fait d'autres choses horribles au retour de la fonction, car le pointeur sur FILE n'est pas le même).
Le plus simple dans ton cas est de faire :
dans la fonction qui appelle recursively_list_files() et de passer le pointeur sur FILE à cette fonction, dont le prototype serait alors
Ainsi, à chaque appel récursif de recursively_list_files() c'est le même pointeur sur FILE qui est passé et utilisé pour écrire dans le fichier ouvert en écriture.
Le
Le plus simple dans ton cas est de faire :
FILE * fichier; fichier = fopen("donnees.txt", "w+");
dans la fonction qui appelle recursively_list_files() et de passer le pointeur sur FILE à cette fonction, dont le prototype serait alors
void recursively_list_files(FILE * fichier, char * dir).
Ainsi, à chaque appel récursif de recursively_list_files() c'est le même pointeur sur FILE qui est passé et utilisé pour écrire dans le fichier ouvert en écriture.
Le
fclose(fichier);devrait aussi être dans la fonction qui appelle recursively_list_files() pour des raisons similaires.
Telnaz
>
[Dal]
Messages postés
6194
Date d'inscription
mercredi 15 septembre 2004
Statut
Contributeur
Dernière intervention
11 octobre 2024
28 avril 2021 à 13:02
28 avril 2021 à 13:02
Merci infiniment, tu es très fort !!