Page 1 sur 1

J'utilise un map avec structure, comment faire recherche ?

Publié : sam. 14/juil./2018 22:45
par caussatjerome
Bonjour ami(e)s codeur !

voici mon bout de code pour imager mon problème :

Code : Tout sélectionner

;Projet Administratif
;on indique au logiciel quelle repertoire surveillé, il vérifie et detecte tous dossiers/fichier créer :
;-1 il vérifie si des fichier précédement indexé ne s'y trouvent plus (alors efface de l'index)
;-2 si l'heure des fichiers, et leurs taille à changer, il met à jour l'index
;-3 si un fichier si trouve, mais n'est pas indexer, alors il vérifie que ce soit pas un doublon : si oui efface : si non ajoute à l'index

;-4fait un check du dossier surveillé via un "tree" ou voir pour routine kernel ?
;-5 : Pourquoi pas une option sync vers (ftp/dossier) /backup / zip ?


;Ce mode de check permet de façon optimale d'avoir une méthode fiable de trie de mes dossiers administratif !
;car l'utilisateur à juste à créer des sous dossier par rubriques (Assurances\EDF...) puis à ajouter les fichiers au bon emplacement depuis l'explorateur.
;si il y a des doublons (un même fichier mais nommé différemment) il notifie l'utilisateur qui peut décider celui a effacer.

;-----------------------------------
Structure fichier_interne
  emplacement_fichier.s     ;-emplacement et nom du fichier (chemin relatif à la racine a mettre en place plus tard, pour l'instant complet).
  date_creation.s           ;prise via routine filesysteme
  taille.l                  ;Taille du fichier
EndStructure

;-variable globale
Global NewMap systemfile.fichier_interne() ;clef de reference=hash de chaque fichier indexer
Global racine.s                    ;dossier racine à surveiller
Global file_index.s="index.dat"           ;nom fichier d'index
Global version.l=1
Global titre.s="Administratif - AntiDoublon"
Global quit.l                             ;arrête les thread et le programme lorsqu'a + 0
Global thread_error.l                     ;permetra de notifier des erreurs d'enregistrement de l'index
emplacement_user_param.s=GetUserDirectory(#PB_Directory_ProgramData)+"Administratif\AntiDoublon\param.ini";emplacement des parametres de l'utilisateur
If FileSize(GetUserDirectory(#PB_Directory_ProgramData)+"Administratif")=-1:CreateDirectory(GetUserDirectory(#PB_Directory_ProgramData)+"Administratif\"):EndIf

If FileSize(GetUserDirectory(#PB_Directory_ProgramData)+"Administratiff\AntiDoublon")=-1:CreateDirectory(GetUserDirectory(#PB_Directory_ProgramData)+"Administratif\AntiDoublon"):EndIf

Procedure read_disk_index();procedure qui va lire le fichier index et charger en mémoire l'index map
  ;et va aussi faire un check des fichier par la même occasion
Debug "Lecture du fichier disk index"
Protected id_f.l,hash.s,ligne.s
id_f.l=OpenFile(#PB_Any,racine+file_index,#PB_Ascii)
If id_f.l;si fichier index ouvert
  While Eof(id_f.l)=0
    ligne.s=ReadString(id_f.l,#PB_Ascii)
    hash.s=StringField(ligne.s,1,",")
    systemfile(hash.s)\date_creation=StringField(ligne.s,2,",")
    systemfile(hash.s)\emplacement_fichier=StringField(ligne.s,3,",")
    systemfile(hash.s)\taille.l=Val(StringField(ligne.s,4,","))
    If FileSize(StringField(ligne.s,3,","))<0:DeleteMapElement(systemfile(),hash):EndIf
  Wend
CloseFile(id_f):ProcedureReturn MapSize(systemfile())
Else;fichier index erreur d'ouverture
ProcedureReturn 0
EndIf
EndProcedure

Procedure thread_update_index(n.l);thread qui régulièrement met à jour le fichier d'index (vérifie toutes les 10 secondes si la mapsize a changer)
Debug "Lancement du thread update disk index"  
Protected id_f.l,hash.s,ligne.s,lastmapsize.l
Shared thread_error.l;-permet de notifier l'utilisateur lors d'erreur de sauvegarde de l'index !
lastmapsize.l=0
Repeat
If MapSize(systemfile())<>lastmapsize.l
id_f.l=CreateFile(#PB_Any,racine.s+file_index,#PB_Ascii)
If id_f
ForEach systemfile()
hash.s=MapKey(systemfile())
ligne.s=hash.s+","+systemfile(hash.s)\date_creation+","+systemfile(hash.s)\emplacement_fichier+","+Str(systemfile(hash.s)\taille)
WriteStringN(id_f.l,ligne.s,#PB_Ascii)
Next
CloseFile(id_f)
Debug "index disque mis à jour."
thread_error.l=0
lastmapsize.l=MapSize(systemfile())
Else;erreur ouverture fichier d'index
thread_error.l=1:Delay(2200):Debug "erreur ouverture disk index, essais dans 2 secondes..."
EndIf
Else
Delay(5000):Debug "Attente mise à jour de l'index mémoire."
EndIf
Until quit.l=1
Debug "fin du thread update index"
EndProcedure

Procedure.s Scan_Directory(source.s,type=0,rek=0) ; Source="repertoire",type 0=fichier 1=dossier 2=dossier et fichier, indice
;total.s = scan_Directory(PathRequester("test",""))
;position=2
Protected s_name.s,s_type.l,s_fullname.s,sortie.s
If Right(source, 1) <> "\" : source + "\" : EndIf
If ExamineDirectory(rek, source, "*.*")
While NextDirectoryEntry(rek)
s_name.s = DirectoryEntryName(rek) : s_type = DirectoryEntryType(rek)
Select s_type
Case #PB_DirectoryEntry_File
If type=0 Or type=2
s_fullname.s = source + s_name
sortie.s + s_fullname.s+Chr(13)
EndIf
Case #PB_DirectoryEntry_Directory
If s_name <> "." And s_name <> ".."
If type=1 Or type=2
sortie.s + source+s_name+Chr(13)
EndIf
sortie.s + Scan_Directory(source + s_name,type, rek + 1)
EndIf
EndSelect
Wend
FinishDirectory(rek)
ProcedureReturn sortie.s
EndIf
EndProcedure

Procedure thread_check_racine(n.l);(pas encore utilisé) verifie les fichiers dans racine
  Debug "lancement du thread check racine"
Protected fichier.s,fichiers.s,a.l,hash.s
Repeat
fichiers.s=scan_Directory(racine,0)
For a=1 To CountString(fichiers.s,Chr(13))
fichier.s=StringField(fichiers.s,a,Chr(13))
If fichier<>racine+file_index;ignore le fichier d'index en lui même
hash.s=FileFingerprint(fichier.s,#PB_Cipher_SHA2,256)
systemfile(hash)\emplacement_fichier=fichier.s
systemfile(hash)\date_creation=FormatDate("%dd/%mm/%yyyy %hh:%ii:%ss",GetFileDate(fichier.s,#PB_Date_Modified))
systemfile(hash)\taille=FileSize(fichier.s)
EndIf
Next a
Debug "Nombre de fichier scanné : "+Str(CountString(fichiers.s,Chr(13)))
Until quit.l=1
Debug "Fin du thread check racine"
EndProcedure

UseSHA2Fingerprint()

If FileSize(emplacement_user_param)<0;fichier de param inexistant
  MessageRequester(titre.s,"Configuration du logiciel au premier lancement,"+#CRLF$+"Veuillez indiquez le dossier à surveiller.",#PB_MessageRequester_Ok)
  racine.s=PathRequester("Dossier à surveiller : ",GetUserDirectory(#PB_Directory_Documents))
  If racine.s
    OpenFile(0,emplacement_user_param)
    WriteStringN(0,racine.s)
    CloseFile(0);a sauvegarder le chemin racine a surveiller
  Else
   End
  EndIf
Else;paramétrage déjà fait
  OpenFile(0,emplacement_user_param)
  racine.s=ReadString(0,#PB_Ascii)
  CloseFile(0);a sauvegarder le chemin racine a surveiller
EndIf

If FileSize(racine.s+file_index.s)>0
Debug "index chargé, nombre de fichier : "+Str(read_disk_index());si fichier d'index déjà existant : alors le charge
CreateThread(@thread_update_index(),0)
Else             ;si non scandirectory et indexation
CreateThread(@thread_update_index(),0)
Debug "Scan de premier lancement"
fichiers.s = scan_Directory(racine,0)
For a=1 To CountString(fichiers.s,Chr(13))
fichier.s=StringField(fichiers.s,a,Chr(13))
If fichier.s<>racine+file_index
hash.s=FileFingerprint(fichier.s,#PB_Cipher_SHA2,256)
systemfile(hash)\emplacement_fichier=fichier.s
systemfile(hash)\date_creation=FormatDate("%dd/%mm/%yyyy %hh:%ii:%ss",GetFileDate(fichier.s,#PB_Date_Modified))
systemfile(hash)\taille=FileSize(fichier.s)
EndIf
Next a
Debug "Nombre de fichier scanné : "+Str(CountString(fichiers.s,Chr(13)))
EndIf

;-maintenant boucle principal qui gere l'affichage des notifications
;test de recherche dans la map :
For a=1 To 10:Delay(1000):Next a
quit.l=1
For a=1 To 10:Delay(1000):Next a

If FindMapElement(systemfile(),"11a62cf53b1fdf8972c048e8fe3d6c5af9208f17717094904cc9874664dc691a"):Debug "hash trouvé":EndIf
If FindMapElement(systemfile.fichier_interne(),"20/06/2018 00:19:53"):Debug "date trouvé":EndIf
If FindMapElement(systemfile.fichier_interne(),"70984"):Debug "taille trouvé":EndIf
End
Vous l'aurez compris je cherche à créer un logiciel qui surveille un dossier racine et tous ce qui ce qui est créer modifier ou supprimé est indexer, modifier ou supprimé de l'index.

le but de ce programme est administratif (j'ai 600 go de fichiers à nettoyer sur mon nas, et les logiciels anti doublon existant ne me conviennent pas, donc l'idée : je me tappe la visualisation de mes fichier et les déplace dans des sous dossiers correspondant (assurance..) qui se trouve dans le nouveau répertoire surveiller "racine", donc si le fichier existe déjà mon programme m'affiche une notif et me laisse choisir quelle fichier conserver.

Vous comprenez je pense mon problème : je souhaite vérifier dans ma map structuré, chercher par nom de fichier/ date/ emplacement, snas pour autant faire un filefingerprint systématique pour avoir le hash...

Quelqu'un peut m'aider svp ?
Par avance merci !!

Re: J'utilise un map avec structure, comment faire recherche

Publié : dim. 15/juil./2018 0:08
par poshu
Il faut utiliser une base de données. Ça sera plus pratique, plus rapide et moins consommant en mémoire. PB embarque sqlite qui est absolument idéal dans ce genre de situation et très simple à utiliser (falsam a balancé plein de tuto dans la section débutant).

Re: J'utilise un map avec structure, comment faire recherche

Publié : dim. 15/juil./2018 1:14
par caussatjerome
Merci, je vais allé regarder les tutos.

Re: J'utilise un map avec structure, comment faire recherche

Publié : dim. 15/juil./2018 7:45
par Marc56
Alternative possible pour synchroniser rapidement des fichiers (Windows) utiliser l'attribut archive.

Cet attribut, positionné automatiquement par l'OS, est mis sur tout nouveau fichier et remis dès qu'un fichier / répertoire est modifié.
Il est géré par PB
Il est aussi utilisable avec des commandes comme Xcopy.
On peut copier déplacer des fichiers et indiquer s'il faut garder ou réinitialiser l'attribut.

Si la sauvegarde est sur un NAS avec un filesystem un*x l'attribut archive n'existe pas, mais on peut indiquer à Samba d'utiliser l'attribut +x (inutile en dos) avec une option dans le smb.conf (map archive = yes)

:wink:

[Résolu partiellement] logiciel anti doublon (en console)

Publié : dim. 15/juil./2018 12:30
par caussatjerome
Voiçi mon code pour faire déjà le gros de mon boulot detrie, si cela peut servire à quelqu'un :

Code : Tout sélectionner

;Projet Anti-Doublon
;on indique au logiciel quelle repertoire surveillé, il vérifie et detecte tous dossiers/fichier créer :
;-1 scandirectory nous donne la liste des fichiers, leurs emplacements, et le total de fichier
;-2 lance un thread qui va scanner les fichiers un par un et tenir une map systemfile(HASH.s)=Emplacement du fichier
;-2b via une variable (global/shared) compteur_scan.l (qui servira dans la boucle for/next indique le nombre de fichier déjà scanner/traiter
;-2c dans cette boucle si le hash du fichier scanner est déjà utiliser dans la map = doublon alors on efface, sinon on ajoute a la map
;-2d on incrémente un (global/shared) compteur_delete.l qui undique le nombre de fichiers supprimé car doublon.
;-3 le programme principale sert uniquement à l'affichage de la progression, et du nombre de fichiers supprimé
;-4 une variable Global QUIT.L permet de fermer proprement le thread
;------------------

;-variable globale
Global NewMap systemfile.s();clef de reference=hash de chaque fichier indexer
Global titre.s="Anti-Doublon"
Global racine.s;emplacement racine à scanné
Global quit.l                             ;arrête les thread et le programme
Global compteur_scan.l
Global compteur_delete.l
Global fichiers.s;listes des fichiers généré par scandirectory

Procedure.s Scan_Directory(source.s,type=0,rek=0) ; Source="repertoire",type 0=fichier 1=dossier 2=dossier et fichier, indice
;total.s = scan_Directory(PathRequester("test",""))
;position=2
Protected s_name.s,s_type.l,s_fullname.s,sortie.s
If Right(source, 1) <> "\" : source + "\" : EndIf
If ExamineDirectory(rek, source, "*.*")
While NextDirectoryEntry(rek) And quit.l=0
s_name.s = DirectoryEntryName(rek) : s_type = DirectoryEntryType(rek)
Select s_type
Case #PB_DirectoryEntry_File
If type=0 Or type=2
s_fullname.s = source + s_name
sortie.s + s_fullname.s+Chr(13)
EndIf
Case #PB_DirectoryEntry_Directory
If s_name <> "." And s_name <> ".."
If type=1 Or type=2
sortie.s + source+s_name+Chr(13)
EndIf
sortie.s + Scan_Directory(source + s_name,type, rek + 1)
EndIf
EndSelect
Wend
FinishDirectory(rek)
Debug "fin du (sous)scan "+Str(rek)
ProcedureReturn sortie.s
EndIf
EndProcedure

Procedure thread_filefingermap(n.l);verifie les fichiers dans racine
Protected fichier.s,hash.s
Shared compteur_scan.l,compteur_delete.l
For compteur_scan=1 To CountString(fichiers.s,Chr(13))
fichier.s=StringField(fichiers.s,compteur_scan,Chr(13))
If fichier
hash.s=FileFingerprint(fichier.s,#PB_Cipher_SHA2,256)

If systemfile(hash.s)<>""; si il y a déjà un fichier identitique...
  DeleteFile(fichier.s,#PB_FileSystem_Force)
  compteur_delete+1
Else; sinon on ajoute a la map
  systemfile(hash)=fichier.s
EndIf

EndIf
If quit.l=1:Break:EndIf
Next compteur_scan
Debug "fin du thread fingerprintmap"
EndProcedure

UseSHA2Fingerprint()
racine.s=PathRequester(titre,GetUserDirectory(#PB_Directory_Desktop))
If racine
fichiers.s=scan_Directory(racine,0):total_fichier.l=CountString(fichiers.s,Chr(13))
OpenConsole(titre+" "+Str(total_fichier)+" a scanner.")
th=CreateThread(@thread_filefingermap(),0)
Repeat
  Delay(1000)
  ConsoleTitle(titre+" "+Str(total_fichier-compteur_scan)+" restant a scanner.")
  If compteur_delete>0 And lastdelete<>compteur_delete
    PrintN(Str(compteur_delete)+" fichiers supprimé.")
    lastdelete=compteur_delete;permet d'éviter l'affichage d'une meme info..
  EndIf
Until total_fichier=compteur_scan Or IsThread(th)=0
Delay(5000)
CloseConsole()
EndIf
End
Merci pour vos réponses, mais le sqlite me parait compliqué (je suis un peut rebuté).

Re: J'utilise un map avec structure, comment faire recherche

Publié : dim. 15/juil./2018 16:33
par Kwai chang caine
J'ai testé ça m'a bien éffacé un doublon de film que j'avais créé :D
Heureusement au passage que la copie avait pas foiré :lol:
Merci du partage 8)

Re: [Résolu partiellement] logiciel anti doublon (en console

Publié : dim. 15/juil./2018 17:28
par poshu
caussatjerome a écrit :Merci pour vos réponses, mais le sqlite me parait compliqué (je suis un peut rebuté).
Malheureusement, y'a pas vraiment d'autre solution : une map, c'est fait pour chercher dans sa hashtable, ça va pas être capable de chercher dans les champs d'une structure.
Tu peux toujours faire une grosse loop foreach sur l'ensemble des éléments de ta map mais c'est va vite devenir lent et consommer beaucoup de ressources pour rien...

Re: J'utilise un map avec structure, comment faire recherche

Publié : lun. 16/juil./2018 19:17
par caussatjerome
Oui en effet, j'y ai pensé raison pour laquelle je cherchait une autre solution, le petit programme que j'ai créer simplement pour faire un index de shafingerprint et emplacements et suppression de doublon, me suffit pour l'instant car cela va me permettre d'effacer les fichier en double/triple/quadruple exemplaire sur mes disques :mrgreen:

Mais à la longue je verrais pour faire quelque chose de plus sympa :D

Re: J'utilise un map avec structure, comment faire recherche

Publié : lun. 16/juil./2018 20:50
par poshu
Je t'encourage vraiment à essayer un peu plus SQLite. Pour commencer, tu peux utiliser un outil graphique pour construire ta base de donnée : ça t'évitera d'avoir à la créer directement en SQL; perso j'utilise DB Browser for SQLite.
Pour le reste, tu n'as que deux fonctions SQL à apprendre pour débuter : INSERT et SELECT. SQL est une techno standard, donc si les tutos que tu trouves ici ne te plaisent pas, tu peux consulter n'importe quelle autre source d'information sur internet; ça marchera avec PB.