Vodič za WatchService u Javi NIO2

1. Pregled

U ovom ćemo članku istražiti WatchService sučelje Java NIO.2 API-ja datotečnog sustava. Ovo je jedna od manje poznatih značajki novijih IO API-ja koji su uvedeni u Javi 7 zajedno FileVisitor sučelje.

Da biste koristili WatchService sučelje u svojim aplikacijama, morate uvesti odgovarajuće klase:

import java.nio.file. *;

2. Zašto koristiti WatchService

Uobičajeni primjer da se razumije što usluga radi zapravo je IDE.

Možda ste primijetili da su IDE-i uvijek otkriva promjenu u datotekama izvornog koda koji se događaju izvan sebe. Neki IDE-i vas obavještavaju pomoću dijaloškog okvira tako da možete ponovno učitati datoteku iz datotečnog sustava ili ne, drugi jednostavno ažuriraju datoteku u pozadini.

Slično tome, noviji okviri poput Play također prema zadanim postavkama izvršavaju vruće ponovno učitavanje programskog koda - kad god izvršavate uređivanja iz bilo kojeg uređivača.

Ove aplikacije koriste značajku tzv obavijest o promjeni datoteke koji je dostupan u svim datotečnim sustavima.

U osnovi, možemo napisati kod za anketiranje datotečnog sustava radi promjena na određenim datotekama i direktorijima. Međutim, ovo rješenje nije skalabilno, pogotovo ako datoteke i direktoriji dosegnu stotine i tisuće.

U Javi 7 NIO.2, WatchService API nudi skalabilno rješenje za nadgledanje direktorija za promjene. Ima čisti API i toliko je dobro optimiziran za izvedbu da ne trebamo implementirati vlastito rješenje.

3. Kako djeluje Watchservice?

Da biste koristili WatchService značajke, prvi korak je stvaranje a WatchService primjer pomoću java.nio.file.FileSystems razred:

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

Dalje, moramo stvoriti put do direktorija koji želimo nadgledati:

Put puta = Paths.get ("pathToDir");

Nakon ovog koraka, put moramo registrirati uslugom straže. U ovoj su fazi dva važna pojma koja treba razumjeti. The StandardWatchEventKinds razred i WatchKey razred. Pogledajte sljedeći registracijski kod samo da biste razumjeli gdje svaki pad. Slijedit ćemo ovo s objašnjenjima istih:

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

Ovdje primijetite samo dvije važne stvari: Prvo, API poziv za registraciju puta uzima instancu usluge promatranja kao prvi parametar iza kojeg slijede varijabilni argumenti StandardWatchEventKinds. Drugo, vrsta povrata postupka registracije je a WatchKey primjer.

3.1. The StandardWatchEventKinds

Ovo je klasa čiji primjerci službi za čuvanje govore o vrstama događaja koje treba pratiti u registriranom imeniku. Trenutno se mogu paziti na četiri moguća događaja:

  • StandardWatchEventKinds.ENTRY_CREATE - aktivira se kada se izvrši novi unos u praćeni direktorij. To bi moglo biti zbog stvaranja nove datoteke ili preimenovanja postojeće datoteke.
  • StandardWatchEventKinds.ENTRY_MODIFY - aktivira se kada se izmijeni postojeći unos u praćenom direktoriju. Sva događanja uređuju datoteku. Na nekim će platformama pokrenuti čak i promjena atributa datoteke.
  • StandardWatchEventKinds.ENTRY_DELETE - aktivira se kada se unos izbriše, premjesti ili preimenuje u gledani direktorij.
  • StandardWatchEventKinds.OVERFLOW - aktivirano za ukazivanje na izgubljene ili odbačene događaje. Nećemo se puno usredotočiti na to

3.2. The WatchKey

Ova klasa predstavlja registraciju imenika sa satnom uslugom. Njegov primjerak vraća nam služba straže kada registriramo direktorij i kada pitamo službu straže jesu li se dogodili događaji za koje smo se registrirali.

Usluga Watch ne nudi metode povratnog poziva koje se pozivaju kad god se dogodi neki događaj. Možemo ih anketirati na više načina kako bismo pronašli ove podatke.

Možemo koristiti anketa API:

WatchKey watchKey = watchService.poll ();

Ovaj API poziv vraća se odmah. Vraća sljedeći ključ za gledanje u redu u bilo kojem događaju koji se dogodio ili nulu ako se nisu dogodili registrirani događaji.

Također možemo koristiti preopterećenu verziju koja traje pauza argument:

WatchKey watchKey = watchService.poll (dugo čekanje, jedinice vremenske jedinice);

Ovaj API poziv sličan je prethodnom u povratnoj vrijednosti. Međutim, blokira za pauza jedinice vremena da daju više vremena unutar kojeg se događaj može dogoditi umjesto da se nula odmah vrati.

Napokon, možemo koristiti uzeti API:

WatchKey watchKey = watchService.take ();

Ovaj posljednji pristup jednostavno blokira dok se ne dogodi događaj.

Ovdje moramo primijetiti nešto vrlo važno: kada WatchKey instancu vraća bilo koji od anketa ili uzeti API-ji, neće zabilježiti više događaja ako se ne pozove API za resetiranje:

watchKey.reset ();

To znači da se instanca ključa za gledanje uklanja iz reda usluga za gledanje svaki put kad se vrati operacijom ankete. The resetirati API poziv vraća ga u red čekanja na više događaja.

Najpraktičnija primjena usluge promatrača zahtijevala bi petlju unutar koje kontinuirano provjeravamo promjene u promatranom direktoriju i u skladu s tim obrađujemo. Da bismo to primijenili, možemo se poslužiti sljedećim idiomom:

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

Stvorimo ključ sata za pohranu povratne vrijednosti operacije ankete. Petlja while blokirat će se sve dok se uvjetni izraz ne vrati ni s ključem sata ili nulom.

Kad dobijemo ključ sata, tada while petlja izvršava kôd unutar njega. Koristimo WatchKey.pollEvents API za vraćanje popisa događaja koji su se dogodili. Zatim koristimo a za svakoga petlja za obradu jednog po jednog.

Nakon što se obrade svi događaji, moramo nazvati resetirati API za ponovno stavljanje ključa za gledanje u red čekanja.

4. Primjer promatranja direktorija

Budući da smo pokrili WatchService API u prethodnom pododjeljku i kako interno djeluje, kao i kako ga možemo koristiti, sada možemo pogledati cjelovit i praktičan primjer.

Iz razloga prenosivosti, pripazit ćemo na aktivnosti u korisničkom početnom direktoriju, koji bi trebao biti dostupan na svim modernim operativnim sustavima.

Kôd sadrži samo nekoliko redaka koda, pa ćemo ga zadržati u glavnoj metodi:

javna klasa DirectoryWatcherExample {public static void main (String [] args) {WatchService watchService = FileSystems.getDefault (). newWatchService (); Put puta = Paths.get (System.getProperty ("user.home")); path.register (watchService, StandardWatchEventKinds.ENTRY_CREATE, StandardWatchEventKinds.ENTRY_DELETE, StandardWatchEventKinds.ENTRY_MODIFY); Tipka WatchKey; while ((key = watchService.take ())! = null) {for (WatchEvent event: key.pollEvents ()) {System.out.println ("Vrsta događaja:" + event.kind () + ". zahvaćena datoteka : "+ event.context () +". "); } key.reset (); }}}

I to je sve što stvarno moramo učiniti. Sada možete pokrenuti klasu da biste počeli gledati direktorij.

Kada dođete do korisničkog kućnog direktorija i izvršite bilo koju aktivnost manipulacije datotekama, poput stvaranja datoteke ili direktorija, promjene sadržaja datoteke ili čak brisanja datoteke, sve će to biti zabilježeno na konzoli.

Na primjer, pod pretpostavkom da idete kući korisnika, desnom tipkom miša kliknite prostor, odaberite `novo -> datoteka` stvoriti novu datoteku i zatim joj dati ime testFile. Zatim dodate malo sadržaja i spremite. Izlaz na konzoli izgledat će ovako:

Vrsta događaja: ENTRY_CREATE. Datoteka na koju se odnosi: New Text Document.txt. Vrsta događaja: ENTRY_DELETE. Datoteka na koju se odnosi: New Text Document.txt. Vrsta događaja: ENTRY_CREATE. Datoteka zahvaćena: testFile.txt. Vrsta događaja: ENTRY_MODIFY. Datoteka zahvaćena: testFile.txt. Vrsta događaja: ENTRY_MODIFY. Datoteka zahvaćena: testFile.txt.

Slobodno uredite putanju koja vodi do bilo kojeg direktorija koji želite gledati.

5. Zaključak

U ovom smo članku istražili neke od rjeđe korištenih značajki dostupnih u Java 7 NIO.2 - API-jevima datotečnog sustava, posebno WatchService sučelje.

Također smo uspjeli proći korake izgradnje aplikacije za praćenje direktorija kako bismo demonstrirali funkcionalnost.

Kao i uvijek, puni izvorni kod za primjere korištene u ovom članku dostupan je u projektu Github.


$config[zx-auto] not found$config[zx-overlay] not found