Astuces de recherche...
Home
- Accueil & nouveautés
- Les newsgroups VB
- Téléchargements
- L'équipe
- Nous contacter
- Liens
Rubriques
- Toutes les questions
- Affichage & graphismes
- Algorithmique
- API
- Base de registre
- Bases de données
- Contrôles
- Date & heure
- Déploiement
- Divers
- Erreurs & problèmes
- Fichiers & dossiers
- Généralités
- Impression
- Internet & mails
- Math
- Multimédia
- Réseaux
- Structures de données
- Texte & strings
- VB .Net
- VB Script
- VBA
- Windows

Question 169

Comment lister les fichiers d'un répertoire ?

Introduction

Il est souvent utile de récupérer la liste des fichiers d'un répertoire. On peut le faire de différentes manières. Cet article présente 2 façons efficaces de le faire. La première méthode est pure VB, elle utilise la fonction Dir. La seconde est un rien plus compliquée, elle utilise les API FindFirstFile et FindNextFile.

Cet article présente l'utilisation de Dir et des API FindFirstFile/FindNextFile, en se limitant volontairement à la simple énumération des fichiers d'un répertoire. Ces 2 méthodes permettent de faire beaucoup plus de choses, telles que filtrer les fichiers en fonction de leurs noms ou attributs, de récupérer des informations comme la taille, la dernière date d'accès, la date de création, etc. Tout ceci est expliqué en détails dans l'article complémentaire de celui-ci : Comment filtrer les fichiers d'un répertoire ?.

Utilisation simplifiée de la fonction Dir

La fonction Dir permet de récupérer les noms des fichiers d'un répertoire. Le premier appel à Dir se fait en précisant en paramètre le chemin de recherche. Il retourne le nom du premier fichier trouvé. Les appels successifs à Dir se font sans arguments. Ils renvoient alors les noms des fichiers suivants. Quand il n'y a pas ou plus de fichiers, la fonction retourne une chaîne vide. Note : on trouve parfois écrit "Dir$". Cette forme est équivalente à Dir.

Exemple

Le code suivant retourne les noms de tous les fichiers du répertoire "c:\temp". Il retourne les fichiers en lecture seule ("read-only"), mais pas les fichiers cachés ni les sous-répertoires :

    Dim FileName As String
    Dim Path As String
    Dim Filter As String

    Path = "c:\temp\*.*"

    FileName = Dir(Path)
    While FileName <> ""
        Debug.Print FileName
        FileName = Dir
    Wend

Une importante limitation de la fonction Dir est qu'elle n'est pas réentrante : cela signifie que l'on ne peut pas faire un appel à Dir au sein d'un autre appel à Dir. Ainsi, il n'est pas possible d'écrire une fonction récursive permettant de lister les fichiers des sous répertoires avec Dir. La suite de cet article montre comment on peut le faire avec les API.

Utilisation des API FindFirstFile et FindNextFile

La fonction FindFirstFile permet de retrouver le premier fichier d'un répertoire. Pour retrouver les fichiers suivants du même répertoire, on appelle FindNextFile. Le principal avantage de ces fonctions est qu'elles retournent plus d'informations que Dir. Ceci est expliqué en détails dans l'article Comment filtrer les fichiers d'un répertoire?

Les API FindFirstFile et FindNextFile ont aussi la propriété d'être réentrantres. On peut donc les utiliser au sein d'une fonction récursive pour lister une arborescence de répertoires et de sous-répertoires.

Contrairement à l'idée reçue, l'usage de FindFirstFile et FindNextFile n'est pas (tellement) plus rapide en VB que l'utilisation de Dir. Cela est dû au fait que ces API retournent une chaîne "null terminated" (terminée par un zéro binaire), ce qui oblige à une manipulation assez coûteuse pour la remettre au format VB. Ceci dit, cette méthode garde un léger avantage en terme de performances, qui ne sera réellement visible que lors de l'exploration de répertoires contenant de très nombreux fichiers.

Exemple

Le code suivant fait la même chose que l'exemple précédent :

Option Explicit

' Déclaration des constantes
Private Const MAX_PATH = 260
Private Const INVALID_HANDLE_VALUE = -1

' Déclaration des API
Private Declare Function FindFirstFile Lib "kernel32" Alias "FindFirstFileA" _
       (ByVal lpFileName As String, lpFindFileData As WIN32_FIND_DATA) As Long
Private Declare Function FindNextFile Lib "kernel32" Alias "FindNextFileA" _
       (ByVal hFindFile As Long, lpFindFileData As WIN32_FIND_DATA) As Long
Private Declare Function FindClose Lib "kernel32" (ByVal hFindFile As Long) As Long

' Déclaration des Types
Private Type FILETIME
    dwLowDateTime As Long
    dwHighDateTime As Long
End Type

Private Type WIN32_FIND_DATA
    dwFileAttributes As Long
    ftCreationTime As FILETIME
    ftLastAccessTime As FILETIME
    ftLastWriteTime As FILETIME
    nFileSizeHigh As Long
    nFileSizeLow As Long
    dwReserved0 As Long
    dwReserved1 As Long
    cFileName As String * MAX_PATH
    cAlternate As String * 14
End Type

Private Function ListDirectory(Path As String) As Boolean
    Dim lpFindFileData As WIN32_FIND_DATA
    Dim hFindFile As Long
    Dim fileName As String
    
    ListDirectory = False

    hFindFile = FindFirstFile(Path, lpFindFileData)
    If hFindFile <> INVALID_HANDLE_VALUE Then
        Do
            fileName = Mid$(lpFindFileData.cFileName, 1, InStr(lpFindFileData.cFileName, Chr$(0)) - 1)
            Debug.Print fileName
        Loop Until FindNextFile(hFindFile, lpFindFileData) = 0
        ListDirectory = True
    End If
    FindClose hFindFile
End Function


Private Sub Command1_Click()

    Call ListDirectory("c:/tempo/*.*")
End Sub

Remarques

On peut également faire ce type de tâches avec FSO. Cependant, l'usage de FSO a beaucoup d'inconvénients comme on peut le voir dans l'article suivant de la FAQ : Quels sont les désavantages du FSO (File System Object) ?

Pour aller plus loin

Voir aussi :

Date de publication : 13 septembre 2007
Dernière modification : 06 mars 2008
Rubriques : Fichiers & dossiers
Mots-clés : liste, lister, fichiers, fichier, dossiers, dir, dir$, FindFirstFile, FindNextFile, API