VBFileFind : Recherche de fichiers pour remplacer
celle de Windows
https://github.com/PatriceDargenton/VBFileFind
Ancien dépôt : https://codes-sources.commentcamarche.net/source/52496
Documentation : VBFileFind.html
Code source : VBFileFind.vbproj.html
http://patrice.dargenton.free.fr/CodesSources/index.html
Version 1.09 du 03/08/2024
Occasionnellement, il arrive qu'on ait besoin de chercher des fichiers sur son disque dur. Il serait absurde de diviser la puissance utile de sa machine par deux juste pour pouvoir utiliser un moteur de recherche local, simplement par négligence à bien ranger ses fichiers ! Mais lorsque malgré tout on a vraiment besoin d'une recherche efficace, rien n'est plus énervant qu'un logiciel qui passe son temps à chercher à l'intérieur des milliers de fichiers zip sur votre disque dur. Qui plus est, lorsque ledit logiciel trouve un fichier dans un dossier, mais qu'il ne le trouve plus lorsqu'on remonte dans le dossier parent (en y incluant bien tous les sous-dossiers) la conclusion est implacable : le système de recherche de Windows XP est quasi-inutile. Celui de Vista a été amélioré avec la possibilité d'exclure la recherche dans les zip, mais là pour le coup, on ne peut pas appeler une amélioration la division par deux des performances générales du système par rapport à XP (je n'ai pas eu l'occasion de tester suffisamment Windows 7). Et comme j'imagine que corriger les bugs de XP est vraiment le dernier des soucis de Microsoft (XP est sur le point d'être placardisé une fois pour toute), alors voici un logiciel pour remplacer le système de recherche de XP. Je suis parti d'une excellente source en C# sur CodeProject. J'y ai notamment ajouté la gestion de l'argument en ligne de commande, ce qui permet de l'appeler depuis l'explorateur de fichier, comme la recherche intégrée de fichiers de XP. J'ai aussi ajouté la prise en compte des recherches insensibles à la casse, en combinant les recherches avec le type d'encodage :
- Recherche
sensible ou insensible à la casse (minuscules/majuscules) ;
- Recherche
sur un octet (ASCII/ANSI) ou deux octets (Unicode), ou les deux à la
fois ;
- Recherche
avec ou sans les sous-dossiers ;
- Recherche
par dates min./max. ;
- Recherche
par taille min./max. ;
- Mémorisation
des options de recherche ;
- Signalement
des erreurs (ex.: fichier inaccessible, faut de droit ou parce que utilisé par
un autre logiciel) ;
- Ouverture
des fichiers trouvés dans le bloc-notes, avec recherche automatique de la 1ère
occurrence ;
- Recherche
via l'explorateur de fichiers, avec le bouton droit sur un dossier sélectionné.
Table des matières
Comment
trier les fichiers dans un ListView ?
Différences
entre Recherche et Indexation
Version
1.01 du 21/11/2010 : Première version
Version
d'origine en C# du 24/04/2010
Ajouter le
menu contextuel via le bouton +, quitter VBFileFind,
puis lancer une recherche via l'explorateur de fichier de Windows, en
sélectionnant un dossier avec le bouton droit de la souris, puis en cliquant
sur "Rechercher avec VBFileFind".
Après de
multiples recherches plus ou moins laborieuses, j'ai fini par déterminer les
spécifications d'un ListView triable
(SortableListView) qui va bien (en mode d'affichage
détaillé surtout) :
- Code VB
simple, sans références externes (pas de DirInfo, FileInfo, ... : la ListView doit
pouvoir contenir n'importe quel type d'objet, pas seulement des fichiers ou
dossiers), générique donc, par exemple une classe ucSortableListView
complète dans un seul fichier source (avec interface en mode design, on doit
pouvoir passer facilement de VB à C# ou l'inverse) ;
- La
classe doit dériver de ListView, de façon à pouvoir
remplacer un ListView facilement dans le code
source ;
- On doit
voir aussi ses propriétés en mode design dans Visual Studio ;
- Tri
selon le type de données (Chaîne, Int, Long, Date, ... avec le code source
extensible) et non pas selon la chaîne représentant une date, une taille de
fichier, ... (si possible définir un CompareTo
générique, à condition que cela ne complique pas le code source, cela doit au
contraire le simplifier) ;
- Ajout
d'élément via un tableau d'objet (car on ne connait pas le type à
priori) :
En fait il y a une astuce : il faut passer
par la propriété Tag du ListView :
Me.sortableListView.Columns.Add("String Field").Tag = GetType(String)
Me.sortableListView.Columns.Add("DateTime Field").Tag =
GetType(DateTime)
Me.sortableListView.Columns.Add("Int Field").Tag = GetType(Integer)
Me.sortableListView.Columns.Add("Double Field").Tag = GetType(Double)
- Affichage
des flèches haut/bas selon le tri appliqué sur l'une des colonnes : le code
doit être simple, pas d'API Win32 ni d'usine à gaz pour afficher une petite
image ! Comme dans l'explorateur de Windows, on peut aussi griser
légèrement la colonne actuellement triée, à condition de ne pas effacer
certaines zones coloriées, par exemple si les items sont des dossiers coloriés
(ce qui indique ici des dossiers dont l'accès n'a pas été autorisé) ;
- Taille
de fichier : ne doit pas être limité à int32 (comme le DataGridView :
2 Go max., du coup les codes sources qui l'utilisent affichent la taille en Ko
au lieu d'octets !). On doit donc pouvoir implémenter le CompareTo avec un Long aussi bien qu'un Int32. Le format
d'affichage vient après, la solution est d'utiliser deux colonnes distinctes,
une avec la taille du fichier en octets (long = int64), et une autre colonne
avec la taille du fichier formatée en mode texte (Octets, Ko, Mo, Go, To), c'est
la colonne qui est visible, tandis que l'autre est masquée. Si on clique sur
l'entête de la colonne pour trier les fichiers par taille de fichier, alors on
applique le tri sur l'autre colonne qui contient la longueur en octets ;
- Tips
possible (exemple : chemin complet si on laisse la souris sur
l'item) : cela est déjà fait dans le ListView de
base ;
- Pendant
le tri, la classe doit générer un événement Sablier, de façon à suspendre les
manipulations externes (cela complique un peu le code, mais c'est nécessaire
pour éviter de figer l'application), et pour pouvoir afficher par exemple
"Tri en cours...", puis "Tri terminé." ;
- Le tri
doit être désactivable (une fonction de désactivation
doit enlever le tri : ListViewItemSorter, rétablir
les couleurs avant le tri, et enlever l'icône de la colonne triée).
VBFileFind est un logiciel de recherche de fichiers, il n'indexe
pas le contenu de vos fichiers : l'avantage, c'est qu'il n'est pas nécessaire
de mettre à jour en permanence un index à chaque fois qu'un fichier est modifié
sur votre disque dur. L'inconvénient, c'est que lors de la recherche, on est
obligé de tenir compte à la volée de plusieurs formats différents de données :
ANSI ou Unicode, sensible à la casse ou bien insensible, ce qui oblige à
convertir l'ensemble du volume de donnée à comparer sous chacun de ses formats.
Avec un logiciel d'indexation, un format unique (ou éventuellement plusieurs)
est enregistré dans l'index, et la recherche n'a pas besoin de parcourir les
données, il suffit de parcourir l'arborescence de l'index, sous une forme de
dictionnaire des mots présents dans l'ensemble du contenu indexé, ce qui est
instantané (mais qui peut prendre beaucoup d'espace disque). C'est un peu comme
lorsque l'on consulte l'index d'un livre pour savoir si le livre traite de tel
sujet et à quelle page, sans avoir besoin de parcourir le livre en totalité
(voir VBTextFinder).
Google n'indexe
jamais les accents ni les majuscules, ni la ponctuation, par contre il conserve
en cache le texte complet, d'une part pour afficher correctement un court
extrait de l'occurrence trouvée dans son contexte, au-dessous du lien trouvé,
et d'autre part dans le cas où la page indexée n'existe plus, la copie cache
permet quand même de la consulter dans l'état où elle se trouvait lors de
l'indexation. Mais le cache ne sert pas pour la recherche, Google ne peut pas
distinguer une recherche avec ou sans accents, majuscules ou ponctuation. Tous
les deux mois, la totalité du web accessible (via au moins un lien hypertexte)
est automatiquement indexée, il n'y a pas besoin de faire quoi que ce soit pour
cela. On peut cependant donner des directives via un fichier Robot.txt situé à
la racine d'un site web pour exclure certaines pages, ou demander une fréquence
de mise à jour plus élevée, ... En principe, une page web dont vous seul
connaissez l'existence sur votre site ne sera jamais indexée (à condition
d'avoir laisser un fichier index.html dans le même dossier, ce qui évite la
consultation du contenu du dossier). Dans les pages Html, le format d'encodage
est précisé en clair dans l'entête du document.
L'encodage ASCII/ANSI consiste à utiliser un seul octet pour coder les
caractères, comme les américains n'utilise pas les accents, une table de 95
caractères suffit dans la plupart des cas (256 caractères au maximum, soit 2^8
bits = un octet). Cela fait gagner 50% d'espace disque par rapport à l'Unicode, mais ce dernier permet d'encoder tous les caractères
de chaque langue, c'est donc ce dernier qui est utilisé dès que l'ASCII est
insuffisant. Lors d'une recherche, on ne peut pas toujours savoir si c'est l'un
ou l'autre qui est utilisé, les fichiers textes sont souvent en ASCII (mais on
peut choisir le format Unicode, par exemple pour conserver les caractères
exotiques).
Dès que le mot
est trouvé dans le fichier, la lecture du fichier s'arrête, de sorte que si
vous recherchez un texte fréquent, la recherche sera rapide, mais si vous
cherchez un texte rare, n'importe où sur votre disque dur, alors la totalité du
contenu de votre disque dur sera examinée. La fréquence affichée avec les
autres informations de résultat indique justement le volume de données lu par
rapport au volume total des données. Une fréquence proche de 100% indique que
le mot recherché est toujours présent au début de chaque fichier examiné, alors
qu'une fréquence proche de 0% indique que les fichiers ont été parcourus en
totalité sans succès.
La vitesse de
recherche dépend de plusieurs facteurs, le débit de lecture varie entre 1 et
100 Mo/sec. Si vous recherchez à la fois en Unicode et ASCII, la vitesse sera
divisée par 2, si vous recherchez en mode insensible à la casse, la vitesse
sera divisée par 3, et si vous recherchez avec toutes ces options, elle sera
divisée par 6. La première recherche sera assez lente, mais une seconde
recherche utilisera le cache disque de Windows, de sorte qu'on pourra atteindre
90 ou 100 Mo/sec., d'après ce que j'ai pu constater
(on n'entend plus l'accès au disque dur les fois suivantes), mais il doit bien
y avoir une limite, car Windows ne peut pas stocker tout le contenu du disque
dur en RAM ! La vitesse semble aussi dépendre de la taille moyenne des fichiers
(sans doute du fait que plus le fichier est gros, plus sa fragmentation est
probable), mais il n'est pas évident de comprendre tous les facteurs en jeu.
- Option
pour signaler ou pas qu'il y a des dossiers inaccessibles ;
- Option
de recherche des fichiers seuls, ou des dossiers seuls, ou alors les
deux ;
- Option
de recherche des mots entiers (s'il existe, le caractère avant et après le mot
n'est pas une lettre ni un chiffre ni le caractère souligné) ;
- Option
de recherche en ignorant les accents (voir VBWinDiff) ;
- Option
de recherche dans les archives zip ;
- Une
fois que la recherche est terminée, affichage de l'icône de chaque fichier
trouvé, ainsi que le menu contextuel correspondant au fichier (ou dossier)
trouvé, complété par des actions communes : Ouvrir, Ouvrir via le
bloc-notes, Ouvrir le dossier (ou Explorer à partir d'ici ou du fichier),
Copier, Supprimer ;
- Mémorisation
de plusieurs recherches courantes et récurrentes (on indique le nombre de
recherche que l'on veut conserver, et un ou deux boutons pour parcourir ces
recherches : chaque recherche reprend toutes les options associées à cette
recherche).
https://github.com/PatriceDargenton/VBFileFind/blob/master/Changelog.md
- Si
l'application est iconisée, ne pas changer la taille des colonnes de la zone de
résultats.
- Passage
au .NET Framework 4 Client Profile (puisqu'on n'utilise pas de bibliothèque
spécifique au .NET Framework 4 complet) ;
- Optimisation :
Queue.Contains -> HashQueue.Contains.
- Sauvegarde
de la taille des colonnes ;
- Affichage
de la taille des fichiers et dossiers parcourus (qui 'matchent' ou pas) :
seulement lorsque l'on fait une recherche dans le contenu ; affichage
aussi du nombre de dossiers parcourus (pour voir l'avancement) ;
- DoEvents pour l'affichage des messages : inutile à
priori ;
- BackgroundWorker : option désactivable :
inutile à priori.
- Attente
lors de la première ouverture du bloc-notes (sinon le SendKeys
ne marche pas du premier coup) ;
- Correction
du chemin vers le bloc-notes, pour l'ensemble des versions de Windows (et
vérification si l'exécutable est bien trouvé) ;
- Configuration
des raccourcis clavier pour le bloc-notes (pour ouvrir les fichiers trouvés
lorsque VBFileFind est utilisé sur un Windows en
anglais par exemple).
- Filtre
d'exclusion pour faire des recherches en excluant les fichiers avec certaines
extensions.
- Passage en VB 2013.
- Dédoublonnage des fichiers trouvés, au cas où les filtres de recherche soient redondants ;
- Passage en VB 2010, avec le DotNet 4.0.
- Correction
de l'affichage du temps de recherche (cumul et non total de chaque unité de
temps) ;
- Utilisation
d'un BackgroundWorker au lieu d'un Thread :
c'est plus simple (pas besoin de synchroniser) ; Une tache correspond à un
seul sous-dossier et non à une arborescence (+ réactif), il suffit ensuite de
rafraîchir souvent la barre d'information sur le fichier en cours, et moins
souvent la liste des fichiers trouvés elle-même ;
- Tri des
colonnes du résultat de la recherche, par exemple par date, par taille de
fichier, ou par nom de fichier : SortableListView.
Simplification
du code source en C#:
- Pas de
thread, et donc pas de synchronisation à faire : les délégués permettent
de résoudre le problème classique du fait que seul le thread courant peut
modifier les éléments de l'interface (en WinForm/DotNet) : ajouter un fichier trouvé (le code source
d'origine en C# à été modifié depuis dans le même sens aussi, mais toujours en
utilisant un thread secondaire). Avec un délégué, c'est bien toujours le thread
d'origine qui effectue toutes les tâches, il suffit de laisser un DoEvents approprié pour ne pas figer l'interface.
L'utilisation de la classe clsAfficherMsg se résume à
une déclaration et un appel de fonction : il suffit ensuite de récupérer
les événements, c'est tout !
- File Searcher in C#, By Manfred Bittersam
| 24 Apr 2009
A
freeware file searcher in C#
https://www.codeproject.com/KB/files/filesearcher.aspx
- VBTextFinder
: un moteur de recherche de mot dans son contexte
http://patrice.dargenton.free.fr/CodesSources/VBTextFinder.html
- VBWinDiff : Interface
d'options pour le comparateur WinDiff
http://patrice.dargenton.free.fr/CodesSources/VBWinDiff.html