Scandisc simple pour lister le contenu d'un repertoire (+ des sous-repertoires....)

Description

Bin voila, je pense que tout est dans le titre. C'est un petit programme qui scanne un repertoire et qui ecrit le contenu dans un fichier texte. On peut scanner un disque entier en demandant de scanner le repertoire 'C://'

Chez moi, il met environs 30 secondes pour scanner les 110.000 fichiers de mon disque dur. Je ne sais pas pourquoi... la vitesse est tres tres variable. Je pense qu'il doit garder des informations en mémoire (des fois il met 2sc :)

Ah oui, je l'ai fait avec Visual C++ 5, mais il doit pouvoir tourner assez facilement avec d'autres compilateurs je pense...

Source / Exemple :


#include <windows.h>
#include <stdio.h>
#include <conio.h> 

void Save_En_Tete_Fichier(FILE* f, char *Chemin);																  
void ScanContenuDossiers(char *CurrentDir, FILE* f);

char Indentation[256] = ""; // sert à indenter dans le fichier texte

int main()
{
	FILE *f;
	char Dir_File[_MAX_PATH];
	char Chemin[_MAX_DIR];

	printf("\n\nTaper l'adresse du repertoire a scanner:\n\n");
	printf("par exemple : \"C://WINNT/\"");
	printf("\n\nChemin: ");
	gets(Chemin);

	printf("\n\nTaper le nom du fichier dans lequel sera enregistre les informations :\n\n");
	printf("\n\nChemin: ");
	gets(Dir_File);

	f = fopen(Dir_File,"wt");
	if (f == NULL)
	{
		printf("Erreur lors de l'ouverture du fichier");
		return 0;
	}
	else
	{
		Save_En_Tete_Fichier(f, Chemin);

		printf("Veuillez Patienter ...\n");

		ScanContenuDossiers(Chemin, f);					

		fclose(f);

		printf("Operation reussie !\n");
	}

	return 0;
}

void Save_En_Tete_Fichier(FILE* f, char *Chemin)
{
	////////////////////////////////////////////////////////////////////////////////////////////////
	char *Texte;
	
	// on alloue de la memoire pour enregistrer deja les informations qui sont en en-tete du fichier
	Texte = (char*) malloc((90+strlen(Chemin))*sizeof(char)+1);
		// le +1 sert pour le '\0' à la fin de la chaine car strlen() ne le compte pas.
		// l'ensemble du texte ecrit en dessous fait 90 caracteres (zavez cas compter ;)
	
	// on copie l'en-tete dans Texte
	strcpy(Texte, "Repertoire en cours : ");
	strcat(Texte, Chemin);
	strcat(Texte, "\n");
	strcat(Texte, "--------------------------------------");
	strcat(Texte, "\n\n");
	strcat(Texte, "Fichiers présents : \n\n");

	// on enregistre les données dans notre fichier
	fwrite(Texte, sizeof(char), strlen(Texte), f);

	// on libère la mémoire
	free(Texte);
	////////////////////////////////////////////////////////////////////////////////////////////////
}
void ScanContenuDossiers(char *CurrentDir, FILE *f)
{
	/* ATTENTION, ICI IL FAUT EVITER D'UTILISER DES FONCTIONS COMME STRCPY OU STRCAT QUI RALLENTISSENT ENORMENENT" */
	/* ESSAYEZ DE RAJOUTER UN STRCPY DANS LA BOUCLE DO... LE TEMPS D'EXECUTION VA CONSIDERABLEMENT AUGMENTER */ 

	char Chemin[MAX_PATH];
	WIN32_FIND_DATA wData;
	HANDLE listing;

	// on rajoute *.* à la fin de l'adresse pour FindFirstFile() 
	sprintf (Chemin, "%s*.*", CurrentDir);
	listing = FindFirstFile(Chemin, &wData);
	
	// on enleve le *.* à la fin de l'adresse
	sprintf (Chemin, "%s", CurrentDir);

	if (listing != INVALID_HANDLE_VALUE)
	{
		do
		{
			if ((strcmp(wData.cFileName, ".."))&&((strcmp(wData.cFileName, "."))))
			{
				if (wData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
				{
					// puisque c'est un repertoire, on recupere la nouvelle adresse, et on va rentrer dedans...
					sprintf(Chemin, "%s%s/", CurrentDir, wData.cFileName);
					// avant, on stoque le nom du repertoire dans notre "fichier de listing" (fichier créé par notre programme)
					fprintf(f, "%s+ %s\n", Indentation,wData.cFileName);
					// on indente (car on va rentrer dans un repertoire)
					strcat(Indentation, " |  ");
					// on rappelle la fonction pour qu'elle s'execute dans le repertoire (recurence)
					ScanContenuDossiers(Chemin, f);
					// on enleve l'indentation puisque on ressort du repertoire
					Indentation[strlen(Indentation)-4] = '\0';
							
					// reviens un repertoire en arrière
					int j = strlen(Chemin)-2;
					while (j>0)
					{
						if (Chemin[j] == '/')
						{
							Chemin[j+1] = '\0';
							break;
						}
						j--;
					}
				}
				else // si c'est pas un dossier, c'est un fichier...

					fprintf(f, "%s- %s\n", Indentation,wData.cFileName); // on enregistre le nom du fichier
			
			}
		}while (FindNextFile(listing, &wData));
	}
	FindClose(listing);
}

Conclusion :


Petit coucou à Jcdjcd qui a aussi fait un programme similaire mais qui ne l'a pas mis pour le moment sur le site.

remis à jour le 21 avril 2004 :
- un tout petit peu plus rapide qu'avant...
- avant je ne regardais pas ce que retournait FindFirstFile() <- ne renvoi pas tjours '.' ou '..'
- racourci un peu le source (c'etait redondent à un endroit)

Codes Sources

A voir également

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.