Aide pour réalisation programme de recherche fichiers en doubles
Bonsoir, suite à une autre discussion, j'ouvre celle-ci pour demander des avis quant à la conception d'un programme de recherche de doublons de fichiers.
En préambule, je sais que de tels programmes existent et je ne cherche pas à réinventer la roue, juste me servir de ce programme comme support d'apprentissage 8-)
Rentrons maintenant dans le vif du sujet.
En premier lieu, suite aux conseil avisés reçus auparavant, tout le programme fonctionnera en mode console. Ce n'est qu'une fois fonctionnel que je l'adapterai sous Qt afin d'en faire un programme graphique. En conséquence, le programme devra être bâti pour nécessiter le moins de modifications possible lors de son adaptation sous Qt.
J'ai réfléchi sur papier à la conception des objets, et fait les ébauches suivantes des headers :
- classe DirsToScan : contient les noms des dossiers à scanner et les méthodes d'ajout/suppression de dossier à la classe, ainsi que des méthodes représentant les options à choisir par l'utilisateur pour tous les dossiers.
- classe Directory : utilisée par DirsToScan, contient le chemin absolu d'un dossier à scanner, et les options qui lui sont liées.
- classe Scan : contient le code pour scanner les dossier Directory pointés dans une instance DirsToScan, avec des options diverses.
- classe Profile : charge et sauve dans un fichier un profil utilisateur. Servira particulièrement dans cette ébauche console à fournir les données au programme sans intervention d'un utilisateur.
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55
| #ifndef DIRSTOSCAN_H
#define DIRSTOSCAN_H
/*
La classe DirsToScan représente un ensemble de dossiers à scanner. Chaque
dossier à scanner est représenté par la classe Directory. Dans la classe, les
objets de type Directory sont pointés dans un vector.
** Méthodes et accesseurs publiques : **
Les méthodes addDir() et delDir() permettent respectivement d'ajouter et de
supprimer un dossier. La méthode addDir() autorise des paramètres de
récursivité dans les sous-dossiers, et un paramètre de protection contre le
déplacement ou l'effacement des fichiers contenus dans le dossier ajouté
(ainsi que ses sous-dossiers en cas de récursivité).
setRecursivity(), setDeepRecursivity() et setProtected() sont des accesseurs
qui permettent de modifier le statut des options de récursivité et de
protection de tous les dossiers existants et de définir une option par défaut
pour les ajouts futurs. Par défaut, la récursivité est permise sans limite de
niveau (m_deepRecursivity vaut 0) et le contenu des dossiers n'est pas protégé
(l'algorithme ne conservera qu'une copie des doublons, les autres fichiers
étant supprimés ou déplacés selon les options du scan).
listing() renvoie une liste de string représentant les chemins absolus des
dossiers à scanner (permet d'informer l'utilisateur).
*/
#include <include/Directory.h>
#include <string>
using namespace std;
class DirsToScan
{
public:
DirsToScan();
void addDir(const string &absolutPath);
void addDir(const string &absolutPath, const bool &protectedStatus,
const bool &recursivity, const unsigned int &deepRecursivity);
void delDir(const string &absolutPath);
void setRecursivity(const bool &recursivity);
void setDeepRecursivity(const unsigned int &deepRecursivity);
void setProtected(const bool &protectedStatus);
list<string> listing();
private:
vector<*Directory> m_dirsToScan;
bool m_recursivity = true;
unsigned int m_deepRecursivity = 0;
bool m_protectedStatus = false;
};
#endif // DIRSTOSCAN_H |
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42
| #ifndef DIRECTORY_H
#define DIRECTORY_H
/*
La classe Directory représente un dossier à scanner.
- m_absolutPath : string représentant le chemin absolu du dossier
- 3 autres attribut privés possédant un accesseur SetAttribut() (sans le m_) :
. bool m_recursivity : true / false : récursivité autorisée / interdite
. unsigned int m_deepRecursivity : profondeur de la récursivité (0 = infini)
. bool m_protectedStatus : si true, déclare le dossier comme protégé (pas
d'effacement/déplacement de fichiers doubons dans ce dossier et ses sous-
dossiers éventuels).
- explore() : va explorer le dossier et ses sous-dossiers éventuels pour
lister les fichiers et renvoyer le résultat sous forme de chemins absolus
dans une list<string>. Cette fonction sera appelée par le constructeur et
par setRecursivity() et setDeepRecursivity() s'ils modifient la valeur
existante. Cette fonction prendrait tout son intérêt dans le cadre d'un
multi-threading, permettant un pré-traitement des données au moment de la
sélection des dossiers et avant le lancement d'un scan.
*/
using namespace std;
class Directory
{
public:
Directory(const string &absolutPath, const bool &protectedStatus,
const bool &recursivity, const unsigned int &deepRecursivity);
setRecursivity(const bool &recursivity);
setDeepRecursivity(const unsigned int &deepRecursivity);
setProtectedStatus(const bool &protectedStatus);
private:
list<string> explore();
string m_absolutPath;
bool m_recursivity;
unsigned int m_deepRecursivity;
bool m_protectedStatus;
};
#endif // DIRECTORY_H |
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
| #ifndef SCAN_H
#define SCAN_H
#include <include/DirsToScan.h>
/*
La classe Scan contient la procédure de scan et ses paramètres.
** Méthodes publiques : **
- int loadProfile() : charge un profile de paramètres inscrit dans un fichier
dont on donne le chemin absolu. Renvoie un code différent de 0 en cas
d'erreur.
- int exec() : lance le scan avec les paramètres en vigueur stockés dans des
attributs privés de la classe.
- setNomDuParametre(T ¶metre) : accesseurs à définir pour la modification
des paramètres du scan.
*/
using namespace std;
class Scan
{
public:
Scan(DirsToScan &directories);
int loadProfile(string &profile);
int exec();
void setNomDuParametre(T ¶metre);
private:
/*
paramètres à définir (certains par enumérations ?)
- filtres d'exclusion : fichiers cachés, fichiers système (.dll) et
extensions diverses, taille mini/maxi, etc...
- filtres d'inclusion : par extension
*/
};
#endif // SCAN_H |
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
| #ifndef PROFILE_H
#define PROFILE_H
/*
La classe DirsToScan représente un ensemble de dossiers à scanner. Chaque
dossier à scanner est représenté par la classe Directory. Dans la classe, les
objets de type Directory sont pointés dans un vector.
** Méthodes publiques : **
- load() et save() permettent respectivement de charger et sauvegarder un
profile dans un fichier. Le path absolu du fichier est passé en paramètre
sous forme d'une string. Le renvoie d'un code différent de 0 signale une
erreur.
Un fichier XML serait adapté : à voir pour comment le manipuler...
Contiendrait les balises <absolutPath> <protected> <recursivity>
<deepRecursivity> pour la partie <Directory>, <protected> <recursivity>
<deepRecursivity> pour la partie <DirsToScan>, et les paramètres de scan
dans la partie <Scan>.
*/
using namespace std;
class Profile
{
public:
Profile(DirsToScan &dirsToScan, Directory &directory, Scan &scan);
int load(string &absolutPath);
int save(string &absolutPath);
private:
};
#endif // PROFILE_H |
Questions :
1/ Cette structure des données vous parait-elle viable ? En particulier, faut ils intégrer les données des Directory directement dans DirsToScan ? C'est ce que j'aurai été tenté de faire, mais y a t'il un conteneur du style vector<typeDeDonnées1, typeDeDonnées2, typeDeDonnées3, typeDeDonnées4> qui me simplifierai les choses, à la manière d'un QAbstractItemModel de Qt ?
2/ Quelles sont les classes permettant de naviguer dans une arborescence de dossiers et de lister des fichiers d'un répertoire ?
3/ Pour manipuler les fichier XML (partie profile), une lib externe comme TinyXML est-elle nécessaire ? y a t'il un moyen plus simple de faire (simple fichier texte avec des mots clés à la place des balises, et on sait que aux lignes suivantes ont trouve le bloc de données que l'on cherche ?
Merci d'avance pour votre aide et toute remarque utile sur mon code ou autre :ccool:
Problème pour récupérer un chemin complet de dossier
Bonjour,
En cherchant en C++ un équivalent au QDir de Qt4, je n'ai trouvé qu'une solution nécessitant des librairies de C. Peut on faire un équivalent en C++ "pur" qui m'éviterait de charger des headers de C et d'utiliser des conversions de string vers char ?
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47
| /*
Affichage des fichiers et dossiers contenus dans un répertoire.
Source : http://c.developpez.com/faq/?page=fichiers#FICHIERS_dir_list
*/
#include <cstdio>
#include <dirent.h> // dirent : DIRectory ENTity
#include <string>
void explore(std::string cheminAbsolu)
{
DIR * dossier = opendir(cheminAbsolu.c_str());
if (dossier != NULL)
{
struct dirent * entite; // entité de classe DIRectory ENTity
while ((entite = readdir(dossier)) != NULL)
{
// vérifie si l'entité est un dossier
std::string nomDossier = entite->d_name;
if (nomDossier !="." && nomDossier !="..")
{
if (entite->d_type == DT_DIR)
{
printf("Dossier : \t%s/%s\n",cheminAbsolu.c_str(),entite->d_name);
// récursivité dans le sous dossier
std::string CheminAbsoluSousDossier = cheminAbsolu + "/" + nomDossier;
explore(CheminAbsoluSousDossier);
}
else
{
printf("%s/%s\n",cheminAbsolu.c_str(),entite->d_name);
}
}
}
closedir(dossier);
}
}
int main(void)
{
std::string cheminAbsolu ="/home/cyril/test";
explore(cheminAbsolu);
return 0;
} |
Ouverture en lecture de fichier vide
Bonjour,
J'ai un petit problème qui m'a permis de découvrir le débogage dans code::blocks :mouarf:
J'ai une fonction qui me renvoie la taille d'un fichier. Je me suis rendu compte que cette fonction bloque lors de l'initialisation du flux si on a en paramètre le chemin d'un fichier existant mais vide. Le programme ne plante pas mais semble rester "coincé" sur cette instruction : en mode débogage, je n'arrive pas à passer à l'instruction suivante, et aucun message d'erreur n'apparait.
Comment détecter l'existence d'un fichier vide sans bloquer le programme ?
Voici le code de la fonction :
Code:
1 2 3 4 5 6 7 8 9 10 11 12
| unsigned long long getSize(string filePath)
{
// ouverture du fichier
ifstream fichier(filePath.c_str()); // *** ligne qui bloque si fichier vide ***
// aller en fin de fichier
fichier.seekg( 0 , ios_base::end );
// position de fin de fichier = taille du fichier
unsigned long long size = fichier.tellg();
// fermeture du fichier
fichier.close();
return size;
} |