2013-04-21 25 views
23
import java.io.*; 
import java.nio.file.*; 

public class Tmp { 

    public static void main(String [] args) throws IOException { 
     int count = 0; 
     Path path = Paths.get("C:\\tmp\\"); 
     WatchService ws = null; 
     try { 
      ws = FileSystems.getDefault().newWatchService(); 
      path.register(ws, StandardWatchEventKinds.ENTRY_CREATE, StandardWatchEventKinds.ENTRY_DELETE, 
        StandardWatchEventKinds.ENTRY_MODIFY, StandardWatchEventKinds.OVERFLOW); 
     } catch (IOException ioe) { 
      ioe.printStackTrace(); 
     } 

     while(true) { 
      WatchKey key = null; 
      try { 
       key = ws.take(); 
      } catch(InterruptedException ie) { 
       ie.printStackTrace(); 
      } 

      for(WatchEvent<?> event: key.pollEvents()) { 
       switch(event.kind().name()) { 
        case "OVERFLOW": 
         System.out.println(++count + ": OVERFLOW"); 
         break; 
        case "ENTRY_MODIFY": 
         System.out.println(++count + ": File " + event.context() + " is changed!"); 
         break; 
        case "ENTRY_CREATE": 
         System.out.println(++count + ": File " + event.context() + " is created!"); 
         break; 
        case "ENTRY_DELETE": 
         System.out.println(++count + ": File " + event.context() + " is deleted!"); 
         break; 
        default: 
         System.out.println(++count + ": UNKNOWN EVENT!"); 
       } 
      } 

      key.reset(); 
     }  
    } 
} 

Khi tôi chạy này và sau đó mở Notepad ++ và sau đó tạo ra một tập tin rỗng mới và lưu nó như a.txt trong thư mục C:\tmp\ tôi có kết quả:Tại sao WatchService tạo ra quá nhiều hoạt động?

1: File a.txt is created! 
2: File a.txt is deleted! 
3: File a.txt is created! 

Tại sao vậy? Dường như tệp đã được tạo và sau đó bị xóa và sau đó được tạo lại. Tại sao?

Khi tôi đặt một số văn bản trong các tập tin và lưu nó đầu ra là:

4: File a.txt is changed! 
5: File a.txt is changed! 

Tại sao nó thay đổi hai lần?

+5

Tôi nghĩ rằng hành vi bạn nhìn thấy với WatchService là do cách Notepad ++ và một số mở rộng cách hệ điều hành Windows hoạt động khi thực hiện các hoạt động IO. Tôi đã thấy rằng một cái gì đó giống như "notepad" Windows tiêu chuẩn thường tạo ra hành vi mong đợi nhất. Tôi nghi ngờ rằng nếu bạn sử dụng Process Explorer (http://technet.microsoft.com/en-gb/sysinternals/bb896653.aspx) để theo dõi hoạt động IO ở cấp hệ điều hành, bạn sẽ thấy kết quả tương tự. –

+2

Điều này có thể là do việc ghi nội dung và siêu dữ liệu được thực hiện riêng. – afk5min

Trả lời

0

Sự kiện tạo và xóa tệp đang hoạt động chính xác trong hệ thống của tôi (Window 7 + 1.7.0_21).

Thông báo sự kiện thay đổi được hiển thị số lượng thời gian (n) cho mỗi thao tác Ctrl + s hoạt động trên tệp đó.

 // Removed the "//" after director name as D://tmp" 
     //Added just to see the message with a 1 ms gap. 
     Thread.sleep(1000); // after key.reset(); 

Ví dụ: Nếu chúng ta mở file và tiếp tục nhấn Crtl + s (lưu với ra bất kỳ thay đổi/với những thay đổi). Thông báo sau sẽ hiển thị (nhiều lần) cho mỗi thao tác lưu.

 File YourFileName.txt is changed! 

Lý do nằm trong cửa sổ WatchService so sánh các thay đổi tệp với dấu thời gian thay vì kiểm tra.

mô tả More đưa ra ở đây Platform dependencies

+0

Đó không phải là khoảng cách 1ms, đó là khoảng cách 1 giây. Tất nhiên bạn sẽ không thấy hiệu ứng nếu bạn chờ đợi một thời gian rất dài trong điều khoản máy tính trước khi kiểm tra lại. Đối với điều này: "Lý do là trong cửa sổ WatchService là so sánh các thay đổi tập tin với dấu thời gian thay vì kiểm tra." uh ... cái gì? –

+0

@RobinGreen, Vui lòng cho tôi biết ngoại lệ và câu trả lời của bạn là gì. – VKPRO

0

làm việc này cho tôi

// get the first event before looping 
    WatchKey key = this.watcher.take(); 

    // reset key (executed twice but not invoke the polled events) 
    while (key != null && key.reset()) { 
     // polled events 
     for (final WatchEvent<?> event : key.pollEvents()) { 
     System.out.printf("\nGlobal received: %s, event for file: %s\n", event.kind(), 
      event.context()); 

     switch (event.kind().name()) { 
     case "ENTRY_CREATE": 
      LOGGER.debug("event ENTRY_CREATE"); 
      break; 
     case "ENTRY_DELETE": 
      LOGGER.debug("event ENTRY_DELETE"); 
      break; 
     case "ENTRY_MODIFY": 
      LOGGER.debug("event ENTRY_MODIFY"); 
      break; 
     default: 
      LOGGER.debug("event other [OVERFLOW]"); 
      break; 
     } 
     } 

     key = this.watcher.take(); 
    } 
1

Sửa kiện Xem Dịch vụ của tạo ra hai sự kiện. Khi chúng ta sửa đổi một tệp đã tồn tại, hệ thống tệp đầu tiên tạo ra nó với 0 byte và kích hoạt một sự kiện sửa đổi và sau đó ghi dữ liệu lên nó. Sau đó, nó sẽ kích hoạt sự kiện sửa đổi lần nữa. Đó là lý do tại sao Nó được hiển thị hai sự kiện sửa đổi. Vì vậy, những gì tôi đã làm để giải quyết vấn đề này, tôi chỉ sử dụng truy cập để kiểm tra công việc của tôi nên được kích hoạt một lần duy nhất trên thậm chí đếm

 Path path = null; 
     int count = 0; 

     try { 
      path = Paths.get(new Utility().getConfDirPath()); 
      System.out.println("Path: " + path); 
     } catch (UnsupportedEncodingException e1) { 
      e1.printStackTrace(); 
     } 

     WatchService watchService = null; 
     try { 
      watchService = FileSystems.getDefault().newWatchService(); 
      path.register(watchService, StandardWatchEventKinds.ENTRY_MODIFY,StandardWatchEventKinds.ENTRY_DELETE); 
     } catch (IOException ioe) { 
      ioe.printStackTrace(); 
     } 


     while(true) { 
      WatchKey key = null; 
      try { 
       key = watchService.take(); 
      } catch(InterruptedException ie) { 
       ie.printStackTrace(); 
      } 

      for(WatchEvent<?> event: key.pollEvents()) { 
       switch(event.kind().name()) { 
        case "ENTRY_MODIFY": 
         System.out.println(++count + ": File " + event.context() + " is changed!"); 

         if (count%2==0) { 
          doOnChange(); // do whatever you want 
         } 
         break; 
        case "ENTRY_DELETE": 
         System.out.println(++count + ": File " + event.context() + " is deleted!"); 
         break; 
        default: 
         System.out.println(++count + ": UNKNOWN EVENT!"); 
       } 
      } 

      // reset the key 
      boolean valid = key.reset(); 
      if (!valid) { 
       System.out.println("Key has been unregistered"); 
      } 

     }  
0

Tôi tạo ra một FileWatcher nhỏ Thư viện tiện ích: https://github.com/finsterwalder/fileutils

Nó cho phép đặt thời gian gia hạn. Nhiều sự kiện bên trong thời gian gia hạn được tích lũy và chỉ được kích hoạt một lần.

Bạn không nên sử dụng Notepad ++ cho các thử nghiệm của mình, vì bạn không biết Notepad ++ đang làm gì. Nó có thể được, rằng Notepad + + thực sự là viết một tập tin nhiều lần. Hoặc nó có thể viết một tập tin với một tên khác và đổi tên nó, khi thực hiện hoặc không có gì. Viết mã của riêng bạn để thao tác các tập tin và xem nó.

Các vấn đề liên quan