鍍金池/ 教程/ Java/ Java目錄事件
Java文件屬性
Java FilePermission示例
Java Externalizable實例
Java文件操作
Java文件鎖
Java文件系統(tǒng)
Java異步I/O
Java Reader/Writer
Java File實例
Java FileReader示例
Java控制臺
Java文件所有者權(quán)限
Java通道
Java ByteArrayOutputStream示例
BufferedOutputStream示例
Java FileInputStream示例
Java DataInputStream
Java BufferedInputStream
Java Jar Manifest
Java Console類示例
BufferedWriter示例
Java輸入/輸出教程
Java對象序列化
Java文件教程
Java DataInputStream類型
Java Zip字節(jié)數(shù)組
Java FileWriter示例
FileOutputStream示例
Java PrintStream
Java Scanner類
BufferedInputStream示例
Java字符集
ByteArrayInputStream示例
Java路徑操作
Java DataOutputStream
Java符號鏈接
Java FilterWriter示例
Java Jar API
BufferedReader實例
Java Pipe(管道)
Java jar文件
Java CharArrayReader示例
Java CharArrayWriter示例
Java PushbackInputStream
Java FilterReader示例
Java zip文件
Java InputStream
Java標(biāo)準(zhǔn)輸入/輸出/錯誤流
Java文件內(nèi)容和讀寫
Java FilterInputStream示例
Java內(nèi)存通道
Java路徑
Java令牌和字符串拆分
Java隨機(jī)訪問文件
Java文件樹
Java緩沖區(qū)讀寫
Java FileOutputStream
Java目錄事件
Java FilterOutputStream示例
Java DataOutputStream實例
FileDescriptor示例

Java目錄事件

當(dāng)文件系統(tǒng)中的對象被修改時,我們可以監(jiān)聽watch服務(wù)以獲取警報。java.nio.file包中的以下類和接口提供watch服務(wù)。

  • Watchable接口
  • WatchService接口
  • WatchKey接口
  • WatchEvent接口
  • WatchEvent.Kind接口
  • StandardWatchEventKinds類

Watchable對象表示可以被監(jiān)視的文件系統(tǒng)對象。Watchable對象可以向watch服務(wù)注冊。
Path對象是一個Watchable對象。

WatchService表示觀察服務(wù)。當(dāng)一個對象使用WatchService注冊時,WatchService返回一個WatchKey作為注冊的令牌。WatchEvent表示注冊到監(jiān)視服務(wù)的對象上的事件。 它的kind()方法返回發(fā)生的事件的類型。
它的context()方法返回一個Path對象,它表示事件發(fā)生的條目。count()方法返回特定通知的事件發(fā)生次數(shù)。 如果它返回的值大于1,那么它是一個重復(fù)的事件。

WatchEvent.Kind <T>表示發(fā)生的事件的類型。StandardWatchEventKinds類定義了用于表示事件種類的常量,如下所示。

  • ENTRY_CREATE
  • ENTRY_DELETE
  • ENTRY_MODIFY
  • OVERFLOW

OVERFLOW表示丟失或丟棄的事件。創(chuàng)建觀察服務(wù)用來觀察目錄,以進(jìn)行進(jìn)一步更改。

WatchService ws = FileSystems.getDefault().newWatchService();

要使用Watch服務(wù)注冊目錄,請使用register()方法,該方法將返回一個WatchKey對象作為注冊令牌。

// Get  a  Path  object for C:\myName  directory  to watch
Path  dirToWatch  = Paths.get("C:\\myName");
WatchKey token   = dirToWatch.register(ws, ENTRY_CREATE,  ENTRY_MODIFY,  ENTRY_DELETE);

要取消注冊,請使用WatchKeycancel()方法。當(dāng)注冊目錄時,其WatchKey處于就緒狀態(tài)??梢酝ㄟ^手表服務(wù)注冊多個目錄。

要從監(jiān)視服務(wù)隊列中檢索WatchKey,請使用WatchService對象的take()poll()方法檢索并刪除發(fā)出信號并排隊的WatchKey。
take()方法等待,直到WatchKey可用。poll()方法可用于為等待指定超時時間值。

以下代碼使用無限循環(huán)來檢索發(fā)出信號的WatchKey。

while(true)  {
    WatchKey key  = ws.take();
}

處理事件

WatchKeypollEvents()方法檢索并刪除其所有掛起的事件。它返回一個WatchEvent的列表-List。List的每個元素代表WatchKey上的一個事件。

以下代碼顯示了處理事件的典型邏輯:

while(true)  {
    WatchKey key  = ws.take();
    // Process all  events of  the   WatchKey 
    for(WatchEvent<?> event  : key.pollEvents())  {
       // Process each  event here
    }
}

處理事件后重置WatchKey

如果要重置WatchKey對象,通過調(diào)用它的reset()方法來再次接收事件通知。

reset()方法將WatchKey置于就緒狀態(tài)。如果WatchKey仍然有效,reset()方法返回true,否則它返回false。

如果WatchKey被取消或其監(jiān)視服務(wù)關(guān)閉,它可能會失效。

// Reset   the   WatchKey
boolean isKeyValid = key.reset();
if (!isKeyValid)  {
    System.out.println("No  longer  watching "  + dirToWatch);
}

WatchService是可自動關(guān)閉的??梢栽?code>try-with-resources塊中創(chuàng)建一個WatchService對象,當(dāng)程序退出塊時,它會自動關(guān)閉。

示例

以下代碼顯示了如何實現(xiàn)監(jiān)視服務(wù)以監(jiān)視目錄中的更改。

import static java.nio.file.StandardWatchEventKinds.ENTRY_CREATE;
import static java.nio.file.StandardWatchEventKinds.ENTRY_DELETE;
import static java.nio.file.StandardWatchEventKinds.ENTRY_MODIFY;
import static java.nio.file.StandardWatchEventKinds.OVERFLOW;

import java.io.IOException;
import java.nio.file.FileSystems;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.WatchEvent;
import java.nio.file.WatchEvent.Kind;
import java.nio.file.WatchKey;
import java.nio.file.WatchService;

public class Main {
  public static void main(String[] args) {
    try (WatchService ws = FileSystems.getDefault().newWatchService()) {
      Path dirToWatch = Paths.get("C:\\myName");
      dirToWatch.register(ws, ENTRY_CREATE, ENTRY_MODIFY, ENTRY_DELETE);
      while (true) {
        WatchKey key = ws.take();
        for (WatchEvent<?> event : key.pollEvents()) {
          Kind<?> eventKind = event.kind();
          if (eventKind == OVERFLOW) {
            System.out.println("Event  overflow occurred");
            continue;
          }
          WatchEvent<Path> currEvent = (WatchEvent<Path>) event;
          Path dirEntry = currEvent.context();
          System.out.println(eventKind + "  occurred on  " + dirEntry);
        }
        boolean isKeyValid = key.reset();
        if (!isKeyValid) {
          System.out.println("No  longer  watching " + dirToWatch);
          break;
        }
      }
    } catch (IOException | InterruptedException e) {
      e.printStackTrace();
    }
  }
}