LISTEZ VOS FICHIER FACILEMENT ET RAPIDEMENT

cs_asimengo Messages postés 280 Date d'inscription jeudi 24 mars 2005 Statut Membre Dernière intervention 18 mars 2009 - 2 août 2007 à 18:59
Renfield Messages postés 17287 Date d'inscription mercredi 2 janvier 2002 Statut Modérateur Dernière intervention 27 septembre 2021 - 19 nov. 2007 à 02:55
Cette discussion concerne un article du site. Pour la consulter dans son contexte d'origine, cliquez sur le lien ci-dessous.

https://codes-sources.commentcamarche.net/source/43640-listez-vos-fichier-facilement-et-rapidement

Renfield Messages postés 17287 Date d'inscription mercredi 2 janvier 2002 Statut Modérateur Dernière intervention 27 septembre 2021 74
19 nov. 2007 à 02:55
Le Doevents présent dans la propriété Name y est pour beaucoup.
je viens d'optimiser un peu le code, les temps d'execution de Dir et CDir se valent...

merci de m'avoir incité a revoir la chose ^^
hpfx Messages postés 22 Date d'inscription vendredi 29 août 2003 Statut Membre Dernière intervention 18 novembre 2007
18 nov. 2007 à 18:53
Salut,
juste une remarque,
si on retire le calcul de la taille du fichier et de la date, pour moi Dir() passe devant CDir (et Dir2 et autres)
en fait si vous ne voulez que les nom des fichiers le plus rapidement possible, il suffit d'utiliser Dir().
Je n'y croyais pas moi même, j'ai passé la journée à tester les fameux codes de mvps.org/vbnet et je ne comprenais pas pourquoi mes bench me montrait que dir() est 2 fois plus rapide.

avec ton code (qui implemente dejà le bench) il suffit de commenter un bout de code là... (apres le name)
.AddItem oDir.Name ' & ">" & oDir.FileSize & ">" & oDir.LastWriteDate
idem pour les 3 autres, et là... stupefaction!... Dir() explose tout.... (FSO est nul)
si seulement j'avais sut cela avant, j'aurais gagné une journée... ;)

ce message d'adresse a ceux qui veulement optimiser leur dir()...

en tout cas, bravo pour ton code, j'adore.
Merci.
Renfield Messages postés 17287 Date d'inscription mercredi 2 janvier 2002 Statut Modérateur Dernière intervention 27 septembre 2021 74
3 août 2007 à 21:27
:/ testé avec un caractère unicode au pif, ca passait :(
Utilisateur anonyme
3 août 2007 à 16:53
Ha, désolé de te l'annoncer, mais ca ne marche toujours pas.
J'ai des noms de fichier contenant des hiraganas et katakanas (caractères japonais), la liste est hélas toujours vide.
__
Kenji
Renfield Messages postés 17287 Date d'inscription mercredi 2 janvier 2002 Statut Modérateur Dernière intervention 27 septembre 2021 74
3 août 2007 à 15:08
c'est réglé, Charles Racaud, bonne remarque.
J'utilise mainenant l'API Unicode
Utilisateur anonyme
3 août 2007 à 12:27
Ouah, c'est bien rapide.
Mais quand je liste les fichiers contenant des caractères Unicode dans leurs noms.
Dir ne trouve rien.
Fso les trouve mais remplace par des ? (normal VB gère pas l'Unicode).
CDir ne trouve rien.
Il serait pas mal d'avoir au moins des ? à la place des caractères Unicode comme le fait la méthode par fso.
__
Kenji
cs_asimengo Messages postés 280 Date d'inscription jeudi 24 mars 2005 Statut Membre Dernière intervention 18 mars 2009
2 août 2007 à 22:09
J'ai laissé exprès, pensant reduire les tests pour les cas de recherche d'item valide afin d'accélérer un peu et je pensais que FindNextFile(mhFind, mtFileInfo) reverrait une valeur <=0 si mhFind<=0, mais je n'ai pas testé.
Merci d'avoir disposé de ton temps pour regarder mon commentaire, je pense que ta source m'aidera et plus d'un comme dab.
Renfield Messages postés 17287 Date d'inscription mercredi 2 janvier 2002 Statut Modérateur Dernière intervention 27 septembre 2021 74
2 août 2007 à 21:53
R.A.S., a part que tu fais FindNextFile sans vérifier mhFind

sinon c'est Ok. Coté traitement, tout se passe au final comme dans mon code...
cs_asimengo Messages postés 280 Date d'inscription jeudi 24 mars 2005 Statut Membre Dernière intervention 18 mars 2009
2 août 2007 à 19:12
RECTIFICATION
-------------

Private Function ItemEnCoursValide() As Boolean
Dim nLength As Long

nLength = InStr(mtFileInfo.cFileName, vbNullChar)
If nLength Then
msName = Left$(mtFileInfo.cFileName, nLength - 1)
'# Si le chemin ne commence pas par '.', et que les attributs de l'element listé
'# correspondent a ce que l'on cherche...
If AscW(msName) <> 46 And CBool(mtFileInfo.dwFileAttributes And meRequiredAttributes) Then
'# l'Item en cours est valide, msName contiendra un nom (fichier ou dossier) valide
ItemEnCoursValide = True
Else
msName = vbNullString
End If
End If

End Function
cs_asimengo Messages postés 280 Date d'inscription jeudi 24 mars 2005 Statut Membre Dernière intervention 18 mars 2009
2 août 2007 à 18:59
Bonjour Renf, Je reprends ton brillant travail dans la logique dont je parlais (voir commentaire sur source de Jack). Initialize et MoveNext entraine le positionnement de mtFileInfo directement sur le nom (fichier ou dossier) valide. Il s'agit juste d'une différence algorithmique mais le fond est totalement le même et vient de toi.
Avec l'exemple de ta source je n'arrive pas à déterminer lequel est plus rapide, les temps sont variables. Mais le plus important pour moi c'est d'avoir ton analyse de mon algorithme et expliquer les différences avec le tien, quand aux temps d'exécution, parce que je ne suis pas encore expert dans cette optimisation.
NB: Je ne me suis pas penché sur les commentaires.
------------------------------------------------------------------------------------------------

Option Explicit

Private mhFind As Long
Private meRequiredAttributes As Long
Private mtFileInfo As WIN32_FIND_DATA
Private msName As String
Private msPath As String

'# On démarre une nouvelle enumeration
'# Par default, on accepte tousles atributs
Public Sub Initialize(ByVal vsPath As String, Optional veAttributes As FileAttributes = &HFFFFFFFF)
Dim i As Long

'# Si une recherche etait deja en cours, on la stoppe
If mhFind > 0 Then Call FindClose(mhFind)

'# On récupère le chemin
i = InStrRev(vsPath, "")
If i Then
msPath = Left$(vsPath, i)
Else
msPath = vbNullString
End If

'# Si nous avons 'C:\MonDossier\'
'# Rien ne sera trouvé... on ajoute donc un joker
If i Len(vsPath) Then vsPath vsPath & "*"

'# On démarre la recherche
mhFind = FindFirstFile(vsPath, mtFileInfo)
If mhFind > 0 Then
'# La requete a été acceptée. On enregistre les parametres de la recherche
meRequiredAttributes = veAttributes
'# Permet de passer sur un fichier valide.
If Not ItemEnCoursValide Then Call RechercheProchainItemValide
End If

End Sub

''# Permet de savoir s'il existe une session cDir.
'Public Property Get State() As Long
' State = IIf(mhFind > 0, 1, 0)
'End Property

'# Renvoie le repertoire courant de la recherche
Public Property Get Path() As String
Path = msPath
End Property

'# Renvoie le chemin complet de l'element listé en cours
Public Property Get FullPath() As String
If mhFind > 0 Then FullPath = msPath & msName
End Property

'# Renvoie le nom (du fichier ou dossier) en cours valide.
Public Property Get Name() As String
Name = msName
End Property

Private Function ItemEnCoursValide() As Boolean
Dim nLength As Long

nLength = InStr(mtFileInfo.cFileName, vbNullChar)
If nLength Then
msName = Left$(mtFileInfo.cFileName, nLength - 1)
'# Si le chemin ne commence pas par '.', et que les attributs de l'element listé
'# correspondent a ce que l'on cherche...
If AscW(msName) <> 46 And CBool(mtFileInfo.dwFileAttributes And meRequiredAttributes) Then
'# l'Item en cours est valide, msName contiendra un nom (fichier ou dossier) valide
ItemEnCoursValide = True
End If
End If

End Function

'# Recherche et pointe sur le prochain nom (du fichier ou dossier) valide.
Private Sub RechercheProchainItemValide()
msName = vbNullString
Do
'# on passe a l'element suivant
If FindNextFile(mhFind, mtFileInfo) = 0 Then
Exit Do
ElseIf mhFind > 0 Then
If ItemEnCoursValide Then Exit Do
Else
Exit Do
End If
Loop
End Sub

'# Renvoie les attributs du fichier
Public Property Get Attributes() As VbFileAttribute
Attributes = mtFileInfo.dwFileAttributes
End Property

Public Property Get CreationDate() As Date
CreationDate = FileTimeToDate(mtFileInfo.ftCreationTime)
End Property

Public Property Get LastAccessDate() As Date
LastAccessDate = FileTimeToDate(mtFileInfo.ftLastAccessTime)
End Property

Public Property Get LastWriteDate() As Date
LastWriteDate = FileTimeToDate(mtFileInfo.ftLastWriteTime)
End Property

Public Property Get FileSize() As Variant
Dim xnCurValue(1) As Long
Dim nCurValue As Currency
'# Sacré fichier ! sa taille dépasse les 4Go...
If mtFileInfo.nFileSizeHigh Then
'# On récupère la taille dans deux longs
xnCurValue(0) = mtFileInfo.nFileSizeLow
xnCurValue(1) = mtFileInfo.nFileSizeHigh
'# On place le tout dans un Currency
CopyMemory nCurValue, xnCurValue(0), 8
'# Que l'on redonne en sortie
FileSize = nCurValue
Else
'# Taille < 4Go. Un long suffit : on renvoie directement nFileSizeLow
FileSize = mtFileInfo.nFileSizeLow
End If
End Property

'# Permet de passer à l'element suivant dans la recherche.
Public Sub MoveNext()
Call RechercheProchainItemValide
End Sub

'# Est-ce que la recherche est terminée ?
Public Property Get EOF() As Boolean
EOF (msName vbNullString)
End Property

Private Sub Class_Terminate()
'# On clot la recherche
If mhFind > 0 Then FindClose mhFind
End Sub
Rejoignez-nous