Sprievodca službou WatchService v prostredí Java NIO2

1. Prehľad

V tomto článku sa chystáme preskúmať WatchService rozhranie API súborového systému Java NIO.2. Toto je jedna z menej známych funkcií novších IO API, ktoré boli súčasne zavedené v prostredí Java 7 FileVisitor rozhranie.

Ak chcete použiť WatchService rozhraní vo svojich aplikáciách, musíte importovať príslušné triedy:

import java.nio.file. *;

2. Prečo používať WatchService

Bežným príkladom na pochopenie toho, čo služba robí, je vlastne IDE.

Možno ste si všimli, že IDE vždy detekuje zmenu v súboroch zdrojového kódu ktoré sa stávajú mimo neho samého. Niektoré IDE vás informujú pomocou dialógového okna, aby ste sa rozhodli, či chcete súbor znova načítať zo súborového systému, alebo nie, iné ho jednoducho aktualizujú na pozadí.

Podobne aj novšie rámce, ako napríklad Play, predvolene predvolene tiež rýchlo načítava kód aplikácie - kedykoľvek vykonávate úpravy z ľubovoľného editora.

Tieto aplikácie využívajú funkciu tzv oznámenie o zmene súboru ktorý je k dispozícii vo všetkých súborových systémoch.

V podstate môžeme napísať kód, ktorý požiada súborový systém o zmeny v konkrétnych súboroch a adresároch. Toto riešenie však nie je škálovateľné, najmä ak súbory a adresáre dosahujú stovky a tisíce.

V prostredí Java 7 NIO.2 sa WatchService API poskytuje škálovateľné riešenie na sledovanie zmien v adresároch. Má čisté API a je tak dobre optimalizované na výkon, že nepotrebujeme implementovať svoje vlastné riešenie.

3. Ako funguje služba Watchservice?

Ak chcete použiť WatchService prvkom je vytvorenie a WatchService napríklad pomocou java.nio.file.FileSystems trieda:

WatchService watchService = FileSystems.getDefault (). NewWatchService ();

Ďalej musíme vytvoriť cestu k adresáru, ktorý chceme monitorovať:

Path path = Paths.get ("pathToDir");

Po tomto kroku musíme cestu zaregistrovať u hodinkovej služby. V tejto fáze treba pochopiť dva dôležité pojmy. The StandardWatchEventKinds triedy a WatchKey trieda. Prezrite si nasledujúci registračný kód, aby ste pochopili, kam každý pád spadne. Budeme sa riadiť týmto vysvetlením:

WatchKey watchKey = path.register (watchService, StandardWatchEventKinds ...);

Tu si všimnite iba dve dôležité veci: Najprv volanie API registrácie cesty vezme inštanciu hodinkovej služby ako prvý parameter, za ktorým nasledujú variabilné argumenty StandardWatchEventKinds. Po druhé, návratový typ procesu registrácie je a WatchKey inštancia.

3.1. The StandardWatchEventKinds

Toto je trieda, ktorej inštancie informujú strážnu službu o druhoch udalostí, ktoré majú sledovať v registrovanom adresári. V súčasnej dobe môžete sledovať štyri možné udalosti:

  • StandardWatchEventKinds.ENTRY_CREATE - spustí sa pri vytvorení nového záznamu v sledovanom adresári. Môže to byť spôsobené vytvorením nového súboru alebo premenovaním existujúceho súboru.
  • StandardWatchEventKinds.ENTRY_MODIFY - spustí sa pri úprave existujúceho záznamu v sledovanom adresári. Túto udalosť spustia všetky úpravy súborov. Na niektorých platformách ju spustí dokonca aj zmena atribútov súboru.
  • StandardWatchEventKinds.ENTRY_DELETE - spustí sa pri vymazaní, presunutí alebo premenovaní záznamu v sledovanom adresári.
  • StandardWatchEventKinds.OVERFLOW - spustené na indikáciu stratených alebo zahodených udalostí. Nebudeme sa na to veľmi sústrediť

3.2. The WatchKey

Táto trieda predstavuje registráciu adresára u hodinárskej služby. Jeho inštanciu nám vráti služba hodiniek, keď zaregistrujeme adresár a keď sa služby hodiniek spýtame, či došlo k udalostiam, pre ktoré sme sa zaregistrovali.

Služba Hodinky nám neponúka žiadne metódy spätného volania, ktoré sa volajú vždy, keď dôjde k udalosti. Tieto informácie môžeme vyhľadať iba niekoľkými spôsobmi.

Môžeme použiť anketa API:

WatchKey watchKey = watchService.poll ();

Toto volanie API sa vráti okamžite. Vráti nasledujúci kľúč sledovania v poradí, ktorého ľubovoľné udalosti nastali, alebo nulovú hodnotu, ak nedošlo k žiadnym zaregistrovaným udalostiam.

Môžeme tiež použiť preťaženú verziu, ktorá trvá a čas vypršal argument:

WatchKey watchKey = watchService.poll (dlhý časový limit, jednotky TimeUnit);

Toto volanie API je podobné predchádzajúcemu vo návratovej hodnote. Blokuje však pre čas vypršal jednotky času, ktoré poskytujú viac času, v rámci ktorého môže dôjsť k udalosti, namiesto okamžitého návratu na hodnotu null.

Nakoniec môžeme použiť vziať API:

WatchKey watchKey = watchService.take ();

Tento posledný prístup jednoducho blokuje, kým nenastane udalosť.

Tu si musíme všimnúť niečo veľmi dôležité: keď WatchKey inštancia je vrátená jedným z anketa alebo vziať Ak rozhranie API nevyvolá, nezachytí viac udalostí:

watchKey.reset ();

To znamená, že inštancia kľúča sledovania je odstránená z frontu služieb sledovania zakaždým, keď je vrátená operáciou dotazovania. The resetovať Volanie API ho vráti do poradia čakania na ďalšie udalosti.

Najpraktickejšia aplikácia sledovacej služby by vyžadovala slučku, v rámci ktorej neustále kontrolujeme zmeny v sledovanom adresári a podľa toho postupujeme. Na implementáciu môžeme použiť nasledujúci frazém:

Kľúč WatchKey; while ((key = watchService.take ())! = null) {for (WatchEvent event: key.pollEvents ()) {// process} key.reset (); }

Vytvoríme sledovací kľúč na uloženie návratovej hodnoty operácie dotazovania. Cyklus while bude blokovaný, kým sa podmienený príkaz nevráti buď s klávesom watch, alebo s nulou.

Keď dostaneme kľúč na sledovanie, potom slučka while vykoná kód v ňom. Používame WatchKey.pollEvents API na vrátenie zoznamu udalostí, ku ktorým došlo. Potom použijeme a pre každý slučku, aby ste ich spracovali jeden po druhom.

Po spracovaní všetkých udalostí musíme zavolať na resetovať API na opätovné zaradenie kľúča hodiniek do poradia.

4. Príklad sledovania adresára

Keďže sme pokryli WatchService Rozhranie API v predchádzajúcej podkapitole a to, ako to funguje interne a tiež, ako ho môžeme používať, si teraz môžeme pozrieť na úplný a praktický príklad.

Z dôvodu prenosnosti budeme sledovať aktivitu v domovskom adresári používateľa, ktorý by mal byť k dispozícii vo všetkých moderných operačných systémoch.

Kód obsahuje iba niekoľko riadkov kódu, takže ho ponecháme iba v hlavnej metóde:

public class DirectoryWatcherExample {public static void main (String [] args) {WatchService watchService = FileSystems.getDefault (). newWatchService (); Cesta cesty = Paths.get (System.getProperty ("user.home")); path.register (watchService, StandardWatchEventKinds.ENTRY_CREATE, StandardWatchEventKinds.ENTRY_DELETE, StandardWatchEventKinds.ENTRY_MODIFY); Kľúč WatchKey; while ((key = watchService.take ())! = null) {for (WatchEvent event: key.pollEvents ()) {System.out.println ("Druh udalosti:" + event.kind () + ". Ovplyvnený súbor : "+ event.context () +". "); } key.reset (); }}}

A to je všetko, čo musíme skutočne urobiť. Teraz môžete triedu spustiť a začať sledovať adresár.

Keď prejdete do domovského adresára používateľa a vykonáte akúkoľvek manipulačnú činnosť so súbormi, ako napríklad vytvorenie súboru alebo adresára, zmena obsahu súboru alebo dokonca jeho odstránenie, všetko sa to zaznamená do konzoly.

Napríklad za predpokladu, že prejdete na domovskú stránku používateľa, kliknite pravým tlačidlom myši v priestore a vyberte `nový -> súbor` vytvorte nový súbor a potom ho pomenujte testFile. Potom pridáte nejaký obsah a uložíte. Výstup na konzole bude vyzerať takto:

Druh udalosti: ENTRY_CREATE. Ovplyvnený súbor: Nový textový dokument.txt. Druh udalosti: ENTRY_DELETE. Ovplyvnený súbor: Nový textový dokument.txt. Druh udalosti: ENTRY_CREATE. Ovplyvnený súbor: testFile.txt. Druh udalosti: ENTRY_MODIFY. Ovplyvnený súbor: testFile.txt. Druh udalosti: ENTRY_MODIFY. Ovplyvnený súbor: testFile.txt.

Nebojte sa upraviť cestu smerujúcu do ľubovoľného adresára, ktorý chcete sledovať.

5. Záver

V tomto článku sme preskúmali niektoré z menej bežne používaných funkcií dostupných v rozhraní Java 7 NIO.2 - API súborového systému, najmä WatchService rozhranie.

Podarilo sa nám tiež prejsť krokmi vytvorenia aplikácie na sledovanie adresárov, aby sme demonštrovali funkčnosť.

Úplný zdrojový kód príkladov použitých v tomto článku je ako vždy k dispozícii v projekte Github.