Examinedirectory() et fichier classé par nom

Vous débutez et vous avez besoin d'aide ? N'hésitez pas à poser vos questions
Avatar de l’utilisateur
blendman
Messages : 2017
Inscription : sam. 19/févr./2011 12:46

Examinedirectory() et fichier classé par nom

Message par blendman »

salut

Lorsque j'utilise ExamineDirectory(), j'aimerai avoir les fichiers classés par nom, comme dans l'explorateur windows.

J'ai plusieurs dossiers, contenant des images, numérotées ainsi (je ne peux pas faire autrement) :
Dossier "plant" :
- plant1.png, plant2.png, plant3.png, plant4.png, plant5.png, plant6.png, plant7.png, plant8.png,plant9.png, plant10.png, plant11.png, plant12.png, plant13.png, plant14.png, plant15.png, etc... jusque plant70.png par exemple.

Idem pour d'autres dossiers : arbre (de arbre1.png à arbre30.png), etc...

Or, lorsque je récupère les noms des images, voici la liste que j'obtiens :
- plant1.png, plant10.png, plant11.png, plant12.png, plant13.png, plant14.png, plant15.png, plant16.png, plant17.png, plant18.png, plant19.png, plant2.png, plant20.png, plant21.png, etc...

Vous voyez le problème ?

Je n'ai pas la liste classée par nom, comme dans l'exploration ou dans Xnview ou n'importe quel autre logiciel, mais un pseudo classement.

Vous savez comment récupérer la liste des fichiers classés réellement par leur nom, comme dans l'explorateur windows ?

Merci :)
Mesa
Messages : 1098
Inscription : mer. 14/sept./2011 16:59

Re: Examinedirectory() et fichier classé par nom

Message par Mesa »

C'est comme ça que fonctionne l'ordre alphabétique informatique, en fait, c'est de l'alphanumérique.

Soit tu renommes tes fichiers en ajoutant autant de digit que necessaire, comme ça xxx01.jpg (de 0 à 99), ou xxx001.jpg (de 0 à 999) etc.

Soit tu devras coder un algorithme maison.
Moi j'essaierai de trouver une "RegularExpression" toute faite.

M.
Avatar de l’utilisateur
celtic88
Messages : 309
Inscription : sam. 12/sept./2015 14:31
Localisation : Alger

Re: Examinedirectory() et fichier classé par nom

Message par celtic88 »

Bjr :)

utilise :
SortList(Liste(), Options [, Debut, Fin])
.....i Love Pb :)
Avatar de l’utilisateur
case
Messages : 1528
Inscription : lun. 10/sept./2007 11:13

Re: Examinedirectory() et fichier classé par nom

Message par case »

faut les renommer comme l'indique mesa 01 02 03 04 05 car le tri se fait dans l'ordre alphanumérique et quand il arrive au caractère 2 il se trouve après 1 donc file10.ext se trouve avant file2.ext
alors que le zéro est avant le 1 donc file02.ext se trouve avant file10.ext

l'algo s’arrête au premier caractère différent et tri en fonction de celui ci

blabla1[0.ext]
blabla2[.ext]
lors du tri la partie entre crochet n'est pas évaluée car les premiers caractères différents sont 1 et 2 et comme 1 < 2 le blabla10.ext vas se retrouver avant blabla2.ext
ImageImage
Avatar de l’utilisateur
celtic88
Messages : 309
Inscription : sam. 12/sept./2015 14:31
Localisation : Alger

Re: Examinedirectory() et fichier classé par nom

Message par celtic88 »

et pour info: windows explorer utilise la méthode "Virtual listview" pour lister les fichiers et meme pour le sort ,,,voilà un exemple basic

Code : Tout sélectionner




Global Dim ItemInfo.s(100000)
Global LvHwnd

Procedure WinCallback(hWnd, uMsg, WParam, LParam) 
  
  Select uMsg
    Case #WM_NOTIFY
      Protected *tNMHDR.NMHDR = LParam
      Select *tNMHDR\hwndFrom
        Case LvHwnd
          Select *tNMHDR\code
            Case #LVN_GETDISPINFO
              Protected *tNMLVDISPINFO.NMLVDISPINFO = LParam
              With *tNMLVDISPINFO
                If \item\mask & #LVIF_TEXT
                  \item\pszText = @ItemInfo(\item\iItem)
                  \item\cchTextMax = Len(ItemInfo(\item\iItem))
                EndIf
              EndWith
          EndSelect
      EndSelect
  EndSelect
  
  ProcedureReturn #PB_ProcessPureBasicEvents 
EndProcedure 

If OpenWindow(0, 100, 100, 500, 600, "Test Virtual List-View", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
  ListIconGadget(0, 5, 5, 490, 590, "File", 100, #PB_ListIcon_FullRowSelect | #PB_ListIcon_AlwaysShowSelection|#LVS_OWNERDATA)
  LvHwnd = GadgetID(0)
  
  SetWindowCallback(@WinCallback(),0)
  
  Repertoire$ = GetHomeDirectory() 
  If ExamineDirectory(0, Repertoire$, "*.*")  
    While NextDirectoryEntry(0)
      If DirectoryEntryType(0) = #PB_DirectoryEntry_File
        Type$ = " [Fichier] "
        Taille$ = " (Taille : " + DirectoryEntrySize(0) + ")"
      Else
        Type$ = " [Dossier] "
        Taille$ = "" ; Un Dossier n'a pas de taille
      EndIf
      
      ItemInfo(Iit) = Type$ + DirectoryEntryName(0) + Taille$
      
      Iit +1
    Wend
    FinishDirectory(0)
  EndIf
  
  SendMessage_( LvHwnd, #LVM_SETITEMCOUNT, Iit, 0 
  
  
   SortArray(ItemInfo(), #PB_Sort_Descending) ; )
 
  Repeat
    Evenement = WaitWindowEvent()
  Until Evenement = #PB_Event_CloseWindow
EndIf
.....i Love Pb :)
Mesa
Messages : 1098
Inscription : mer. 14/sept./2011 16:59

Re: Examinedirectory() et fichier classé par nom

Message par Mesa »

Tri alphanumérique de type xxx000*
(*Ne convient pas pour des noms exotiques, par exemple: xx0x00xxx0x.jpg)

Code : Tout sélectionner

Structure fichier
  Nom$
  n.l
EndStructure

NewList fichiers.fichier()

AddElement(fichiers())
fichiers()\Nom$ = "xxx10.jpg"
;   fichiers()\n = 10

AddElement(fichiers())
fichiers()\Nom$ = "xxx2.jpg"
;   fichiers()\n = 2

AddElement(fichiers())
fichiers()\Nom$ = "xxx22.jpg"
;   fichiers()\n = 22

AddElement(fichiers())
fichiers()\Nom$ = "xxx1.jpg"
;   fichiers()\n = 1


If CreateRegularExpression(0, "\d+")
  
  Dim Result$(0)
    
  ForEach fichiers()
    fich$=fich$+fichiers()\Nom$+" "   
  Next
  
  NbResults = ExtractRegularExpression(0, fich$, result$()); à optimiser avec ExamineRegularExpression() ?
  
  ResetList(fichiers())
  For i = 0 To NbResults - 1
    NextElement(fichiers())
    fichiers()\n = Val(Result$(i))
  Next
  
  ; Trie la liste en fonction du champ 'n' qui est un long
  ;
  SortStructuredList(fichiers(), #PB_Sort_Ascending, OffsetOf(fichier\n), TypeOf(fichier\n))
  
  ForEach fichiers()
    Debug fichiers()\Nom$
  Next
  
Else
  MessageRequester("Error", RegularExpressionError())
EndIf
M.
Avatar de l’utilisateur
case
Messages : 1528
Inscription : lun. 10/sept./2007 11:13

Re: Examinedirectory() et fichier classé par nom

Message par case »

pour renommer facilement les fichiers d'un dossier complet avec un nombre de même taille
ne renomme que la première suite de chiffre rencontrée

file_renumber(PathRequester("",""),4)
file1.xxx --->file0001.xxx
file1_2.xxx ---> file0001_2.xxx

donc attention dans une anim par exemple si on a personage1_frame1.png

ca donnera personage0001_frame1.png

---

Code : Tout sélectionner

Procedure file_renumber(dir.s,zero=2) ; deux zero par defaut
  Debug dir
a=ExamineDirectory(#PB_Any,dir,"*.*")
Repeat
  id= NextDirectoryEntry(a)  
  If id
    f$=DirectoryEntryName(a)
    Debug f$
    For chk=1 To Len(f$)
      value=Asc(Mid(f$,chk,1))
      If value>=48 And value<=57
        st=chk : Break
      EndIf
    Next
    Debug Str(st)+f$
    
    If st>0
    
     For chk=st To Len(f$)
      value=Asc(Mid(f$,chk,1))
      If value<48 Or value>57
        en=chk-1 : Break
      EndIf
    Next
    RenameFile(dir+f$,dir+Left(f$,st-1)+RSet(Mid(f$,st,en-st+1),zero,"0")+Right(f$,Len(f$)-en))
    EndIf
  EndIf  
Until id=0
EndProcedure
file_renumber(PathRequester("",""),4)
ImageImage
Avatar de l’utilisateur
blendman
Messages : 2017
Inscription : sam. 19/févr./2011 12:46

Re: Examinedirectory() et fichier classé par nom

Message par blendman »

salut
merci pour les réponses, mais non, je ne peux pas renommer mes 500 fichiers lol
car il faudrait aussi que je change ensuite mes procédures de sauvegarde des maps (qui conservent le nom des images utilisées)
Ensuite j'utilise "plant"+str(i)+".png" dans mon éditeur et dans mon jeu, donc, je devrais encore faire une autre opération
if i < 10
; ajouter un 0 devant voir 2 zéro si j'ai 100 images...
endif

J'ai trouvé une solution un peu bancale mais bon : j'ouvre les fichiers et je les mets ds un array temporaire, que je trie (avec sortarray().
Puis, je copie ces éléments triés dans mon array d'image définitif. Et ça marche pas mal comme ça ^^.

Merci encore pour votre aide ;).

je vais quand même regardé vos procédures :D
Marc56
Messages : 2148
Inscription : sam. 08/févr./2014 15:19

Re: Examinedirectory() et fichier classé par nom

Message par Marc56 »

De l'intérêt d'utiliser des noms de longueur constante (facile avec Rset())

Code : Tout sélectionner

For i = 1 To 10
     Debug "File_" + RSet(Str(i), 3, "0") + ".png"
Next
En plus pour extraire une sauvegarde 'n' il suffit de faire un Val( Right() )
Pas besoin de chercher la valeur numérique dans le nom.

De même pour un fichier avec TimeStamp, utiliser la date au format ISO

Code : Tout sélectionner

Debug "File_" + FormatDate("%yyyy%mm%dd_%hh%ii%ss", Date()) + ".png"
Les fichiers triés par nom le sont alors aussi par date, même déplacés.

PS. Certains programmes (comme TC) sont capable d'afficher les noms par ordre 'naturel' et même en ignorant les accents.

:wink:
Avatar de l’utilisateur
falsam
Messages : 7244
Inscription : dim. 22/août/2010 15:24
Localisation : IDF (Yvelines)
Contact :

Re: Examinedirectory() et fichier classé par nom

Message par falsam »

@Celtic : Sont pas bons tes codes.

Ce que veut Blendman c'est un tri comme celui là
plant1.png
plant2.png
plant10.png
plant11.png
plant21.png
et non pas comme celui là

Code : Tout sélectionner

plant1.png
plant10.png
plant11.png
plant2.png
plant21.png
Configuration : Windows 11 Famille 64-bit - PB 6.03 x64 - AMD Ryzen 7 - 16 GO RAM
Vidéo NVIDIA GeForce GTX 1650 Ti - Résolution 1920x1080 - Mise à l'échelle 125%
Avatar de l’utilisateur
falsam
Messages : 7244
Inscription : dim. 22/août/2010 15:24
Localisation : IDF (Yvelines)
Contact :

Re: Examinedirectory() et fichier classé par nom

Message par falsam »

Liste et expression régulière.

- Rechercher un nombre dans chaque fichier lu : Exemple plant1.png
- formater ce nombre avec des 0 sur la gauche (Rset() : Exemple plant0000000001.png

Rassures toi on ne touche pas au nom original du fichier.

Structure d'un fichier

Code : Tout sélectionner

Structure NewFile
  Key.s
  File.s
EndStructure
-Key contiendra le nom du fichier retouché.
-File contiendra le nom du fichier original.

En fin de code on va trier la liste sur la clé.

Code : Tout sélectionner

Structure NewFile
  Key.s
  File.s
EndStructure

NewList Files.NewFile()
Dim Result$(0)

Directory$ = "Your directory" 

CreateRegularExpression(0, "[0-9]+")

If ExamineDirectory(0, Directory$, "*.png")  
  While NextDirectoryEntry(0)
    If DirectoryEntryType(0) = #PB_DirectoryEntry_File
      AddElement(Files())
      Files()\File = DirectoryEntryName(0)
          
      ExtractRegularExpression(0, Files()\File, Result$())
      
      Files()\Key = ReplaceString(Files()\File, Result$(0), RSet(Result$(0), 10, "0")) 
    EndIf
  Wend
  FinishDirectory(0)
EndIf

SortStructuredList(Files(), #PB_Sort_Ascending | #PB_Sort_NoCase, OffsetOf(NewFile\Key), TypeOf(NewFile\Key)) 
ForEach Files()
  Debug Files()\File
Next
Configuration : Windows 11 Famille 64-bit - PB 6.03 x64 - AMD Ryzen 7 - 16 GO RAM
Vidéo NVIDIA GeForce GTX 1650 Ti - Résolution 1920x1080 - Mise à l'échelle 125%
Avatar de l’utilisateur
Ar-S
Messages : 9478
Inscription : dim. 09/oct./2005 16:51
Contact :

Re: Examinedirectory() et fichier classé par nom

Message par Ar-S »

J'aurai aussi fait un truc du genre mais surement plus long car sans regex :D
Une liste virtuelle renommant les nombres dans la logique 01 02 etc.. et la liste des noms de fichiers en parallèle.
C'est tout de même ballot de ne pas utiliser ce système d'énumération.
~~~~Règles du forum ~~~~
⋅.˳˳.⋅ॱ˙˙ॱ⋅.˳Ar-S ˳.⋅ॱ˙˙ॱ⋅.˳˳.⋅
W11x64 PB 6.x
Section HORS SUJET : ICI
LDV MULTIMEDIA : Dépannage informatique & mes Logiciels PB
UPLOAD D'IMAGES : Uploader des images de vos logiciels
Avatar de l’utilisateur
kernadec
Messages : 1594
Inscription : ven. 25/avr./2008 11:14

Re: Examinedirectory() et fichier classé par nom

Message par kernadec »

bjr à tous
peut etre une solution en utilisant une numérotation hexadécimale :?:
cordialement

Code : Tout sélectionner

For i=0 To 1000
  Debug "fichier_"+Str(i)+"_"+ Hex(i)
Next i
ps: ptit code pour le retour au mode décimale

Code : Tout sélectionner

Procedure.l Hex2Dec(h$)
  ; procedure extraite de CodeArchive/convert auteur : inconnu
  h$=UCase(h$)
  For r=1 To Len(h$)
    d<<4 : a$=Mid(h$,r,1)
    If Asc(a$)>60
      d+Asc(a$)-55
    Else
      d+Asc(a$)-48
    EndIf
  Next
  ProcedureReturn d
EndProcedure
Répondre