În dezvoltarea de aplicații Delphi pentru a sincroniza ceva, de exemplu, fișiere de pe computere diferite, într-un fel sau altul, trebuie să dezvolte un algoritm care poate fi utilizat pentru a identifica în mod unic care fișierele trebuie să fie eliminate dintr-un anumit director, care a muta, redenumi, etc. Algoritmi similari și exemple de utilizare a acestora în practică nu sunt neobișnuite: pe Net puteți găsi o mulțime de variații variate ale codului Delphi cu care puteți urmări schimbările în directoarele și fișierele Windows.
Nu cu mult timp în urmă am întâmpinat o astfel de sarcină - să urmăresc modificările într-un anumit director și să creeze o listă de sarcini pentru sincronizarea fișierelor cu serverul. De vreme ce nu am dezvoltat astfel de algoritmi, a trebuit să amestec expansiunile internetului și să colectez cât mai multe informații pe acest subiect. Ei bine, am decis să difuzez rezultatele căutărilor mele sub forma unui articol separat în blog. Deci, tema de astăzi este monitorizarea schimbărilor în directoare și fișiere prin intermediul Delphi.
Cea mai ușoară și mai ușor accesibilă cale de programare pentru a urmări schimbările în director este chiar și lucrul la cronometru. Semnificația lucrării este că, la începutul programului, este creată o listă de fișiere și subdirectoare în directorul țintă. Apoi, în momentul în care se declanșează temporizatorul, se creează o nouă listă și se compară cu cea anterioară - determină care fișiere au fost adăugate, care au fost șterse / mutate etc. și operațiile de sincronizare sunt efectuate pentru modificările deja determinate. Cum în acest caz, pentru a determina că, să spunem, fișierul Test.txt a fost modificat? De exemplu, puteți calcula de fiecare dată câte un fișier CRC și puteți compara această sumă cu valoarea precedentă. Iată sursa funcției de la www.delphisources.com. pentru a calcula fișierul CRC:
Un exemplu de utilizare a funcției. Creați o nouă aplicație în Delphi cu următoarele componente pe formular:
La deschiderea unui fișier, vom determina dimensiunea acestuia și vom calcula CRC utilizând funcția de mai sus:
Acum, să creăm un fișier text și să scriem o linie, să spunem "Hello World!", Salvează-l, executați programul și calculați CRC. Iată ce sa întâmplat în program:
Deschideți din nou fișierul și înlocuiți majusculele cu majuscule. șirul va arăta ca "salut lume!". Din nou, calculați CRC:
Rețineți că dimensiunea fișierului este aceeași și că conținutul fișierului sa modificat. Acesta este un exemplu suplimentar al faptului că utilizarea drept criteriu de modificare a unui fișier numai dimensiunea sa este o opțiune foarte nesigură și, probabil, chiar incorectă.
Ce se poate spune despre versiunea propusă de monitorizare a modificării directorului cu ajutorul unui cronometru?
Avantajul acestei metode este simplitatea ei. Nu contează ce timer va fi utilizat în funcționare - un timer standard sau un timer de înaltă precizie creat de el însuși. Oricine poate agăța un handler pe cronometru. Dar, odată cu simplitatea acestei opțiuni, ea are și o mulțime de defecte. Iar cea mai importantă dintre aceste neajunsuri este lipsa de fiabilitate.
Nimeni nu vă va oferi garanții că intervalul de timp stabilit al operației de timer va fi suficient pentru a efectua procedura de manipulare. După cum se spune, computerul utilizatorului este întunecat. Puteți, desigur, să stabiliți o cantitate mare de timp și sperăm că handler va lucra la 100% timer, dar este doar o „cârjă“, dar nu și soluția problemelor de fiabilitate a algoritmului.
În plus, de fiecare dată pentru a sorta printr-un număr mare de fișiere - o pierdere inutilă de resurse. Desigur, în această vârstă de procesoare multi-core, resursele de calculator sunt foarte mari, dar, de asemenea, arunca-le peste si fara - nu merita, mai ales dacă se lucrează la crearea unui proiect intensiv de resurse serioase în cazul în care fiecare octet contează.
Și, prin urmare, o modalitate mai rațională de a monitoriza modificările în fișiere și directoare este utilizarea funcțiilor Windows. Există două modalități de lucru:
- Monitorizarea modificărilor în director fără a afișa informații despre modificări, adică o simplă declarație de fapt - a existat o schimbare și ceea ce a fost modificat nu este determinat. Pentru această metodă, se folosește trei funcții: FindFirstChangeNotification. FindNextChangeNotification. FindCloseChangeNotification.
- Monitorizarea modificărilor în directorul cu ieșirea de informații despre elementele modificate. Pentru această metodă, se utilizează o pereche de funcții: CreateFile și ReadDirectoryChangesW.
Ambele metode sunt la fel de convenabile, dar care dintre aceste modalități de a utiliza într-o anumită situație depinde de dvs. Luați în considerare exemple de utilizare a funcțiilor Windows pentru a monitoriza modificările în directoare.
Folosind FindFirstChangeNotification, FindNextChangeNotification, FindCloseChangeNotification
Înainte de a trece la studiul funcțiilor, vom crea un modul de achiziții pentru o muncă ulterioară. Vom urmări modificările din firul (TThread):
Acum, luați în considerare scopul funcțiilor Windows.
FindFirstChangeNotification - Creează un descriptor de notificare a schimbării și stabilește condițiile inițiale pentru trimiterea notificării. Funcția returnează un descriptor (THandle) sau INVALID_HANDLE_VALUE în cazul unei erori:
lpPathName: PChar este calea completă spre director urmată de urmărire. Valoarea acestui parametru nu poate conține o cale relativă sau un șir gol.
bWatchSubtree: boolean - True - indică faptul că modificările la subdirectoare vor apărea și în rezultatul monitorizării.
dwNotifyFilter: DWORD este setul de pavilioane care definesc setările filtrului. Steagurile pot fi:
- FILE_NOTIFY_CHANGE_FILE_NAME (0x00000001) - orice schimbare a numelui fișierului în director sau subdirector. Modificările includ redenumirea, crearea sau ștergerea unui fișier.
- FILE_NOTIFY_CHANGE_DIR_NAME (0x00000002) - orice modificare a numelui directorului din director sau din subdirector. Modificările includ redenumirea, crearea sau ștergerea unui director.
- FILE_NOTIFY_CHANGE_ATTRIBUTES (0x00000004) - orice modificare a atributelor în directorul și subdirectoarele scanate.
- FILE_NOTIFY_CHANGE_SIZE (0x00000008) - modificați dimensiunea fișierului într-un director sau subdirector. O redimensionare este detectată numai când fișierul este scris pe disc.
- FILE_NOTIFY_CHANGE_LAST_WRITE (0x00000010) - modificați timpul ultimei înregistrări din fișier.
- FILE_NOTIFY_CHANGE_SECURITY (0x00000100) - modificați setările de securitate într-un director sau subdirector.
FindNextChangeNotification - indică faptul că sistemul de operare a returnat avizul de semnal de modificare THandle în data viitoare, atunci când modificările sunt descoperite, în funcție de filtru instalat funcția FindFirstChangeNotification.
hChangeHandle: THandle este un descriptor obținut folosind funcția FindFirstChangeNotification.
FindCloseChangeNotification - oprește monitorizarea modificărilor din director.
hChangeHandle: THandle este un descriptor obținut folosind funcția FindFirstChangeNotification.
Funcțiile au devenit acum mai mult sau mai puțin clare pentru noi - rămâne să consolidăm cunoștințele dobândite din experiență. Deci, în primul rând, firul nostru ar trebui să primească două valori: calea spre directorul din spatele căruia vom urma și steagul indicând dacă să monitorizăm subdirectoarele. Noi scriem proiectantul de flux:
Acum, creați următorul Execut:
În manualul Execute de mai sus, monitorizăm modificările din numele fișierului / directorului sau dimensiunea fișierului. În acest caz, așteptăm oricare dintre evenimentele specificate în filtru și vom emite un mesaj. Apropo, vom crea un eveniment pentru a afișa un mesaj despre schimbări, de exemplu:
Acum, totul este gata pentru a testa performanța firului nostru. Creați un nou proiect Delphi și puneți următoarele componente pe formularul principal:
În utilizări conectăm modulul cu firul nostru și declarăm următoarea variabilă:
Acum, scrieți operatorii necesari pentru evenimente:
Rulați programul, selectați directorul pe care doriți să îl monitorizați și faceți clic pe butonul "Urmați". Acum vom încerca să copiem / ștergem un fișier și să vedem un mesaj corespunzător din Memo. Puteți să încărcați gratuit cărți electronice și să îmbinați în director o grămadă de fișiere text - fluxul vă va informa corect despre directorul care se schimbă exact de câte ori mai multe fișiere intrați în director.
Exemplul de mai sus este probabil cel mai simplu, atunci când urmărim doar un eveniment prin care menționăm pur și simplu faptul - au existat schimbări în director. Și ce schimbări - nu vă informăm despre acest lucru. Nici nu putem spune ce sa întâmplat în acest caz. Puteți regla ușor procesorul de mai sus și utilizând funcțiile de mai sus de Windows pentru a defini diferite evenimente pentru fiecare opțiune de modificări, în loc de a folosi WaitForSingleObject WaitForMultipleObjects funcția funcție. Dar vom vorbi despre acest lucru, precum și despre utilizarea metodelor CreateFile și ReadDirectoryChangesW data viitoare.