Ce code est destiner a lister le plus rapidement possible.
Les fichier et les répertoire sous linux.
Avec leur atribbus aux complet.
*/
/*
Les répertoires ce présente comme ceci.
note: remplacer le ~ par celui de votre utilisateur.
mkdir -p ~/rep_racine/rep1
mkdir -p ~/rep_racine/rep2/sous_rep_2_0
mkdir -p ~/rep_racine/rep2/sous_rep_2_1
mkdir -p ~/rep_racine/rep2/sous_rep_2_2
mkdir -p ~/rep_racine/rep2/sous_rep_2_3
mkdir -p ~/rep_racine/rep3
mkdir -p ~/rep_racine/rep2/sous_rep_2_3/sous_sous_rep2
*
le dernier répertoir n'est pas trouver alors que ceux situer dans ~/rep_racine/rep2/ le son
*/
int main()
{
//variable
std::vector<std::string> search_full_path; //retourne un tableau chemin complet de tout les répertoires trouver
std::vector<std::string> search_rep_name; //repertoir seulement,pas encore utilisée
std::vector<std::string> search_file_name; //fichier seulement,pas encore utilisée
std::vector<std::string> stat_info; //information global sur le répertoir ou le dossier,pas encore utilisée
std::string transfere; //variable pour le nom du repertoir en recusiviter, passe en paramettre le répetoire racine.
//code
search_full_path.push_back("/home/taz/rep_racine/"); //valeur par defaut,en cour de dévloppment,rarement utiliser
transfere = "/home/taz/rep_racine";
Full_Search(search_full_path, search_rep_name, search_file_name, stat_info,transfere);
std::cout << "nombre d'élément apres execution " << search_full_path.size() << std::endl; //affiche le nombre d'entrée du tableau
for (long i = 0; i < search_full_path.size(); ++i ) //affiche le contenu du tableaux
{
std::cout << search_full_path[i] << std::endl;
}
std::cout << "affichage terminer" << std::endl;
return 0;
} // main
[quote=panthere007]
Ce code est destiner a lister le plus rapidement possible.
/quote
Le plus rapidement possible ?
Alors tu n'emploies pas du tout la bonne méthode.
td::vector<string> -> string est lent. vector est lent. Combiné les deux c'est affreusement lent.
Et imagine que ton répertoire contienne 10000 répertoires ? Tu fait un vector de 10000 strings ?
Tu as une idée de la consommation mémoire ?
Bref, tu n'iras pas bien loin avec ce genre d'algo.
D'une manière générale quand on veut :
1) Récupérer un ensemble d'objets quelconques.
2) Appliquer un algo sur chacun d'entre eux.
Il ne faut pas essayer de lister ces objets puis parcourir ces objets.
Il faut faire le traitement a chaque objet lors du parcourt. C'est infiniment plus efficace.
Mais on voudrait ne pas avoir à réécrire l'algo de parcourt pour tous les traitements possibles.
Le copier coller, c'est mal.
On va donc faire une fonction de parcourt qui prend en argument une fonction (on appelle ça une callback) de traitement.
Comme ça la fonction de parcourt va appeler la fonction de traitement pour tous les élements parcouru.
Sans faire de liste ni autre structure mémoire aussi consommatrice de RAM que lente car allouée dynamiquement.
Voilà un exemple de code.
C'est du C. Ou du C++. Comme tu veux. Mais pour faire du "plus rapidement possible", je t'invite vivement à oublier le C++.
<hr size="2" width="100%" />#include <stdio.h>
#include <dirent.h>
#include <string.h>
/* Fonction callback appelée lors de l'énumération */
typedef int (*enum_dir_callback)(char *lpDirPath);
/*
* Utilisée par EnumDir pour pouvoir transmettre un buffer en paramètre
* et ainsi ne pas surchrager la pile.
*/
int EnumDirInternal(char *lpDirPath, enum_dir_callback lpCallback, char* lpBuffer)
{
DIR *lpDir; /* Le répertoire courant */
struct dirent *lpChild; /* Un fils du répertoire */
int bContinue; /* Continuer l'énumération ? */
bContinue = 1;
lpDir = opendir(lpDirPath);
/* Si c'est un répertoire */
if (lpDir)
{
/* Appel de la fonction utilisateur */
if (! lpCallback(lpDirPath))
bContinue = 0;
else
{
/* On récupère . et .. */
readdir(lpDir);
readdir(lpDir);
/* Pour tous les fils */
while (1)
{
lpChild = readdir(lpDir);
if (! lpChild) break;
/* Construction d'un chemin complet vers le fils */
strcpy(lpBuffer, lpDirPath);
strcat(lpBuffer, "/");
strcat(lpBuffer, lpChild->d_name);
/*
* Appelle lpCallback pour lpDirPath et tous ses sous répertoires.
* Arrête l'énumération si lpCallback renvoie 0.
*/
int EnumDir(char *lpDirPath, enum_dir_callback lpCallback)
{
char lpFullPath[4096];
Je ne connaissait pas les callback, je vai me panchez dessus
j'ai essayer ton code telle qu'elle , 2 bug voici la première erreur:
surf_find_file_main.cpp: In function ‘int main()’:
surf_find_file_main.cpp:80: warning: deprecated conversion from string constant to ‘char*’
./
./.
la 2eme j'ai change le chemin dans le main par /home/user/rep_racine user étant l'utilisateur et j'obtien
line 10: 5329 Erreur de segmentation
note je compile avec g++ ton code rassemble surtout a du C et pas du C++ (excuse pour la confusion c'est lier aux fait que j'utilise cout et pas printf.
Avec quoi l'a tu compiler ? gcc ?
warning: deprecated conversion from string constant to 'char*'
Mais je n'ai pas eu ce warning. D'après le net, il n'apparait pas sur des versions anciennes. Il est en fait dû au fait que mon "." passé en paramètre de EnumDir est en lecture seule, et donc qu'il ne peut pas être passé en paramètre d'une fonction qui attend un char*. Il faut changer une ou deux signatures en ajoutant const.
line 10: 5329 Erreur de segmentation
Probablement un dépassement des 4096 caractères du tampon. Non pas que tu ais (Ou pas) un chemin de 4096 caractères dans ton home, il y a un bug dans mon source.
En effet, lors de l'appel à EnumDirInternal(lpBuffer, lpCallback, lpBuffer), lpBuffer était modifié pour ajouté un fils, ce qui modifiait aussi le lpDirPath puisqu'ils sont les mêmes lors de cette appel. Bilan cela concaténait le fils 1 avec le fils 2 et ainsi de suite. Donc ça ne listait pas la moitié des répertoires et ça faisait des chemins beaucoup trops longs -> d'où l'erreur de segmentation je pense.
Donc il faut remonter d'un répertoire en sortie d'appel à EnumDirInternal.
Voilà qui devrait aller mieux :
<hr size="2" width="100%" />#include <stdio.h>
#include <dirent.h>
#include <string.h>
/* Fonction callback appelée lors de l'énumération */
typedef int (*enum_dir_callback)(const char *lpDirPath);
/*
* Utilisée par EnumDir pour pouvoir un premier caractère non const.
*/
int EnumDirInternal(char *lpDirPath, enum_dir_callback lpCallback)
{
DIR *lpDir; /* Le répertoire courant */
struct dirent *lpChild; /* Un fils du répertoire */
int bContinue; /* Continuer l'énumération ? */
bContinue = 1;
lpDir = opendir(lpDirPath);
/* Si c'est un répertoire */
if (lpDir)
{
/* Appel de la fonction utilisateur */
if (! lpCallback(lpDirPath))
bContinue = 0;
else
{
/* On récupère . et .. */
readdir(lpDir);
readdir(lpDir);
/* Pour tous les fils */
while (1)
{
lpChild = readdir(lpDir);
if (! lpChild) break;
/* Construction d'un chemin complet vers le fils */
strcat(lpDirPath, "/");
strcat(lpDirPath, lpChild->d_name);
/*
* Appelle lpCallback pour lpDirPath et tous ses sous répertoires.
* Arrête l'énumération si lpCallback renvoie 0.
*/
int EnumDir(const char *lpDirPath, enum_dir_callback lpCallback)
{
char lpPath[4096];
voila un extrait de la sortie le ~ = /home/tonuser
~/rep_racine/rep3/./././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././sous_rep3_2_2
sa me fait pareil si je mai le répertoire /home donc je doit dire que j'ai un peux de pain a suivre
Eventuellement, il peut y avoir un problème avec une arborescence récursive, c'est à dire un link avec un répertoire parent. Mais ta sortie est bizarre.
Tu as essayé sur une arborescence de répertoires plus simple ?
Au vu de la sortie, peut être que "." et ".." ne sont pas les deux premiers répertoires listés... Essaie de remplacer EnumDirInternal par cette fonction (Non testée) :
/*
* Utilisée par EnumDir pour pouvoir un premier caractère non const.
*/
int EnumDirInternal(char *lpDirPath, enum_dir_callback lpCallback)
{
DIR *lpDir; /* Le répertoire courant */
struct dirent *lpChild; /* Un fils du répertoire */
int bContinue; /* Continuer l'énumération ? */
bContinue = 1;
lpDir = opendir(lpDirPath);
/* Si c'est un répertoire */
if (lpDir)
{
/* Appel de la fonction utilisateur */
if (! lpCallback(lpDirPath))
bContinue = 0;
else
{
/* Pour tous les fils */
while (1)
{
lpChild = readdir(lpDir);
if (! lpChild) break;
if (! strcmp(lpChild->d_name, ".") continue;
if (! strcmp(lpChild->d_name, "..") continue;
/* Construction d'un chemin complet vers le fils */
strcat(lpDirPath, "/");
strcat(lpDirPath, lpChild->d_name);
merci pour ta réponse , j'ai pas essayer t'a denière méthode methode, mai je m'en suis inspirer.
le code que je fourni ici fonctionne chez moi, note que le tableau de type vector est facultatif. sinon sa tourne bien.