2014-05-04 4 views
23

में परिवर्तनों के लिए निर्देशिका देखना मैं फ़ाइल परिवर्तनों के लिए एक निर्देशिका देखना चाहता हूं। और मैंने java.nio में वॉच सेवा का उपयोग किया। मैं फाइल बनाई गई घटना के लिए सफलतापूर्वक सुन सकता हूं। लेकिन मैं फ़ाइल संशोधित घटना के लिए नहीं सुन सकता। मैंने official java tutorial की जांच की, लेकिन अभी भी संघर्ष कर रहा है।जावा

यहां स्रोत कोड है।

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

import java.io.File; 
import java.io.IOException; 
import java.nio.file.FileSystem; 
import java.nio.file.Files; 
import java.nio.file.Path; 
import java.nio.file.WatchEvent; 
import java.nio.file.WatchEvent.Kind; 
import java.nio.file.WatchKey; 
import java.nio.file.WatchService; 

public class MainWatch { 

    public static void watchDirectoryPath(Path path) { 
     // Sanity check - Check if path is a folder 
     try { 
      Boolean isFolder = (Boolean) Files.getAttribute(path, 
        "basic:isDirectory", NOFOLLOW_LINKS); 
      if (!isFolder) { 
       throw new IllegalArgumentException("Path: " + path 
         + " is not a folder"); 
      } 
     } catch (IOException ioe) { 
      // Folder does not exists 
      ioe.printStackTrace(); 
     } 

     System.out.println("Watching path: " + path); 

     // We obtain the file system of the Path 
     FileSystem fs = path.getFileSystem(); 

     // We create the new WatchService using the new try() block 
     try (WatchService service = fs.newWatchService()) { 

      // We register the path to the service 
      // We watch for creation events 
      path.register(service, ENTRY_CREATE); 
      path.register(service, ENTRY_MODIFY); 
      path.register(service, ENTRY_DELETE); 

      // Start the infinite polling loop 
      WatchKey key = null; 
      while (true) { 
       key = service.take(); 

       // Dequeueing events 
       Kind<?> kind = null; 
       for (WatchEvent<?> watchEvent : key.pollEvents()) { 
        // Get the type of the event 
        kind = watchEvent.kind(); 
        if (OVERFLOW == kind) { 
         continue; // loop 
        } else if (ENTRY_CREATE == kind) { 
         // A new Path was created 
         Path newPath = ((WatchEvent<Path>) watchEvent) 
           .context(); 
         // Output 
         System.out.println("New path created: " + newPath); 
        } else if (ENTRY_MODIFY == kind) { 
         // modified 
         Path newPath = ((WatchEvent<Path>) watchEvent) 
           .context(); 
         // Output 
         System.out.println("New path modified: " + newPath); 
        } 
       } 

       if (!key.reset()) { 
        break; // loop 
       } 
      } 

     } catch (IOException ioe) { 
      ioe.printStackTrace(); 
     } catch (InterruptedException ie) { 
      ie.printStackTrace(); 
     } 

    } 

    public static void main(String[] args) throws IOException, 
      InterruptedException { 
     // Folder we are going to watch 
     // Path folder = 
     // Paths.get(System.getProperty("C:\\Users\\Isuru\\Downloads")); 
     File dir = new File("C:\\Users\\Isuru\\Downloads"); 
     watchDirectoryPath(dir.toPath()); 
    } 
    } 
+0

क्या ओएस और जावा के संस्करण? – MadProgrammer

+0

विंडोज 8 और जावा 1.7 – Isuru

+2

क्या आपने "स्टॉक" [WatchDir.java] (http://docs.oracle.com/javase/tutorial/essential/io/examples/WatchDir.java) की कोशिश की है? यह कम से कम लिनक्स पर काम करता है। – user3159253

उत्तर

20

असल में आपने गलत घटनाओं की सदस्यता ली है। केवल अंतिम श्रोता ENTRY_DELETE ईवेंट प्रकार के साथ पंजीकृत किया गया है।

घटनाओं के सभी प्रकार के लिए रजिस्टर करने के लिए आप का उपयोग करना चाहिए:

path.register(service, ENTRY_CREATE, ENTRY_MODIFY, ENTRY_DELETE); 
14

चेतावनी! निर्बाध आत्म पदोन्नति!

मैंने जावा 1.7 के WatchService के आसपास एक रैपर बनाया है जो किसी निर्देशिका को पंजीकृत करने और ग्लोब पैटर्न की किसी भी संख्या को पंजीकृत करने की अनुमति देता है। इस वर्ग को छानने का ख्याल रखना होगा और केवल घटनाओं आप में रुचि रखते हैं फेंकना।

DirectoryWatchService watchService = new SimpleDirectoryWatchService(); // May throw 
watchService.register(// May throw 
     new DirectoryWatchService.OnFileChangeListener() { 
      @Override 
      public void onFileCreate(String filePath) { 
       // File created 
      } 

      @Override 
      public void onFileModify(String filePath) { 
       // File modified 
      } 

      @Override 
      public void onFileDelete(String filePath) { 
       // File deleted 
      } 
     }, 
     <directory>, // Directory to watch 
     <file-glob-pattern-1>, // E.g. "*.log" 
     <file-glob-pattern-2>, // E.g. "input-?.txt" 
     ... // As many patterns as you like 
); 

watchService.start(); 

पूरा कोड इस Gist में है।

+0

पूर्ण समाधान के लिए उपरोक्त। हालांकि, एक छोटी सी सिफारिश, ध्यान दें कि उदाहरण केवल जावा 8 पर काम करता है। मुझे गलत मत समझो, मुझे लैम्बडास पसंद है, लेकिन जावा 7 इन दिनों अधिक आम है, इसलिए जब मैंने इसका इस्तेमाल किया तो मुझे इसे जावा 7 में फिर से निकालना पड़ा। मैं जल्द ही उन लोगों के लिए 'निश्चित' संस्करण पोस्ट करता हूं जो जावा 8 का उपयोग नहीं कर सकते हैं – nterry

+0

अरे, प्रयास में शामिल होने के लिए धन्यवाद। जावा 7 समर्थन चक्र समाप्त होने के बाद से मैं जावा 8 पर स्विच करने के लिए काम कर रहा हूं। यही कारण है कि मेरे पास जावा 7 का समर्थन करने के लिए एक अनिवार्य कारण नहीं था। मैं इसे प्रतिबिंबित करने के लिए गिस्ट शीर्षक अपडेट करूंगा। – Hindol

+0

मैंने अभी गिस्ट ज़िप डाउनलोड किया है और जावा 1.7 का उपयोग करके इसे आजमाया है। यह 'आयात java.util.stream' और कुछ' डिफ़ॉल्ट 'विधियों को नहीं ढूंढ सकता है। @nterry क्या आपने जावा 7 संस्करण कहीं भी प्रकाशित किया था? Tnks। – elysch

2

मैंने इसके लिए कुछ कक्षाएं बनाई हैं।

public interface FileAvailableListener { 
    public void fileAvailable(File file) throws IOException; 
} 

और

public class FileChange { 

private long lastModified; 
private long size; 
private long lastCheck; 

public FileChange(File file) { 
    this.lastModified=file.lastModified(); 
    this.size=file.length(); 
    this.lastCheck = System.currentTimeMillis(); 
} 

public long getLastModified() { 
    return lastModified; 
} 
public long getSize() { 
    return size; 
} 
public long getLastCheck() { 
    return lastCheck; 
} 

public boolean isStable(FileChange other,long stableTime) { 
    boolean b1 = (getLastModified()==other.getLastModified()); 
    boolean b2 = (getSize()==other.getSize()); 
    boolean b3 = ((other.getLastCheck()-getLastCheck())>stableTime); 
    return b1 && b2 && b3; 
} 
} 

और

public class DirectoryWatcher { 

private Timer timer; 
private List<DirectoryMonitorTask> tasks = new ArrayList<DirectoryMonitorTask>(); 

public DirectoryWatcher() throws URISyntaxException, IOException, InterruptedException { 
    super(); 
    timer = new Timer(true);   
} 
public void addDirectoryMonitoringTask(DirectoryMonitorTask task,long period) { 
    tasks.add(task); 
    timer.scheduleAtFixedRate(task, 5000, period);  
} 
public List<DirectoryMonitorTask> getTasks() { 
    return Collections.unmodifiableList(tasks); 
} 
public Timer getTimer() { 
    return timer; 
} 
} 

और

class DirectoryMonitorTask extends TimerTask { 

public final static String DIRECTORY_NAME_ARCHIVE="archive"; 
public final static String DIRECTORY_NAME_ERROR="error"; 
public final static String LOCK_FILE_EXTENSION=".lock"; 
public final static String ERROR_FILE_EXTENSION=".error"; 
public final static String FILE_DATE_FORMAT="yyyyMMddHHmmssSSS"; 

private String name; 
private FileAvailableListener listener; 
private Path directory; 
private File directoryArchive; 
private File directoryError; 
private long stableTime; 
private FileFilter filter; 
private WatchService watchService; 
private SimpleDateFormat dateFormatter = new SimpleDateFormat(FILE_DATE_FORMAT); 
private Hashtable<File,FileChange> fileMonitor = new Hashtable<File,FileChange>(); 

public DirectoryMonitorTask(String name,FileAvailableListener listener,Path directory,long stableTime,FileFilter filter) throws IOException { 
    super(); 
    this.name=name; 
    this.listener=listener; 
    this.directory=directory; 
    this.stableTime=stableTime; 
    if (stableTime<1) { 
     stableTime=1000; 
    } 
    this.filter=filter; 
    validateNotNull("Name",name); 
    validateNotNull("Listener",listener); 
    validateNotNull("Directory",directory); 
    validate(directory); 
    directoryArchive = new File(directory.toFile(),DIRECTORY_NAME_ARCHIVE); 
    directoryError = new File(directory.toFile(),DIRECTORY_NAME_ERROR); 
    directoryArchive.mkdir(); 
    directoryError.mkdir(); 
    // 
    log("Constructed for "+getDirectory().toFile().getAbsolutePath()); 

    initialize(); 
    // 
    watchService = FileSystems.getDefault().newWatchService(); 
    directory.register(watchService,StandardWatchEventKinds.ENTRY_CREATE,StandardWatchEventKinds.ENTRY_DELETE,StandardWatchEventKinds.ENTRY_MODIFY); 
    log("Started"); 
} 

private void initialize() { 
    File[] files = getDirectory().toFile().listFiles(); 
    for (File file : files) { 
     if (isLockFile(file)) { 
      file.delete(); 
     } else if (acceptFile(file)) { 
      fileMonitor.put(file,new FileChange(file)); 
      log("Init file added -"+file.getName()); 
     } 
    } 
} 
public SimpleDateFormat getDateFormatter() { 
    return dateFormatter; 
} 
public Path getDirectory() { 
    return directory; 
} 
public FileAvailableListener getListener() { 
    return listener; 
} 
public String getName() { 
    return name; 
} 
public WatchService getWatchService() { 
    return watchService; 
} 
public long getStableTime() { 
    return stableTime; 
} 
public File getDirectoryArchive() { 
    return directoryArchive; 
} 
public File getDirectoryError() { 
    return directoryError; 
} 
public FileFilter getFilter() { 
    return filter; 
} 
public Iterator<File> getMonitoredFiles() { 
    return fileMonitor.keySet().iterator(); 
} 

@Override 
public void run() { 
    WatchKey key; 
    try { 
     key = getWatchService().take(); 
     // Poll all the events queued for the key 
     for (WatchEvent<?> event : key.pollEvents()) {          
      @SuppressWarnings("unchecked") 
      Path filePath = ((WatchEvent<Path>) event).context(); 
      File file = filePath.toFile(); 
      if ((!isLockFile(file)) && (acceptFile(file))) { 
       switch (event.kind().name()) { 
        case "ENTRY_CREATE": 
         //       
         fileMonitor.put(file,new FileChange(file)); 
         log("File created ["+file.getName()+"]"); 
         break; 
         // 
        case "ENTRY_MODIFY": 
         //       
         fileMonitor.put(file,new FileChange(file)); 
         log("File modified ["+file.getName()+"]"); 
         break; 
         // 
        case "ENTRY_DELETE": 
         // 
         log("File deleted ["+file.getName()+"]"); 
         createLockFile(file).delete(); 
         fileMonitor.remove(file);       
         break; 
         // 
       } 
      } 
     } 
     // reset is invoked to put the key back to ready state 
     key.reset(); 
    } catch (InterruptedException e) {    
     e.printStackTrace(); 
    } 

    Iterator<File> it = fileMonitor.keySet().iterator(); 

    while (it.hasNext()) { 
     File file = it.next(); 
     FileChange fileChange = fileMonitor.get(file); 
     FileChange fileChangeCurrent = new FileChange(file); 

     if (fileChange.isStable(fileChangeCurrent, getStableTime())) { 
      log("File is stable ["+file.getName()+"]"); 
      String filename = getDateFormatter().format(new Date())+"_"+file.getName(); 
      File lockFile = createLockFile(file); 
      if (!lockFile.exists()) { 
       log("File do not has lock file ["+file.getName()+"]"); 
       try { 
        Files.createFile(lockFile.toPath()); 
        log("Processing file ["+file.getName()+"]"); 
        getListener().fileAvailable(file);      
        file.renameTo(new File(getDirectoryArchive(),filename)); 
        log("Moved to archive file ["+file.getName()+"]"); 
       } catch (IOException e) {      
        file.renameTo(new File(getDirectoryError(),filename)); 
        createErrorFile(file,e); 
        log("Moved to error file ["+file.getName()+"]"); 
       } finally { 
        lockFile.delete(); 

       } 
      } else {      
       log("File do has lock file ["+file.getName()+"]"); 
       fileMonitor.remove(file); 
      }    
     } else {     
      log("File is unstable ["+file.getName()+"]"); 
      fileMonitor.put(file,fileChangeCurrent); 
     } 
    }  
} 

public boolean acceptFile(File file) { 
    if (getFilter()!=null) { 
     return getFilter().accept(file); 
    } else { 
     return true; 
    }  
} 

public boolean isLockFile(File file) { 
    int pos = file.getName().lastIndexOf('.'); 
    String extension=""; 
    if (pos!=-1) { 
     extension = file.getName().substring(pos).trim().toLowerCase(); 
    } 
    return(extension.equalsIgnoreCase(LOCK_FILE_EXTENSION)); 
} 

private File createLockFile(File file) { 
    return new File(file.getParentFile(),file.getName()+LOCK_FILE_EXTENSION); 
} 

private void createErrorFile(File file,IOException exception) { 
    File errorFile = new File(file.getParentFile(),file.getName()+ERROR_FILE_EXTENSION); 

    StringWriter sw = null; 
    PrintWriter pw = null; 
    FileWriter fileWriter = null; 
    try { 
     //   
     fileWriter = new FileWriter(errorFile); 
     if (exception!=null) { 
      sw = new StringWriter(); 
      pw = new PrintWriter(sw); 
      exception.printStackTrace(pw);  
      fileWriter.write(sw.toString()); 
     } else { 
      fileWriter.write("Exception is null."); 
     } 
     //  
     fileWriter.flush(); 
     // 
    } catch (IOException e) { 
    } finally { 
     if (sw!=null) { 
      try { 
       sw.close(); 
      } catch (IOException e1) {    
      } 
     } 
     if (pw!=null) { 
      pw.close(); 
     } 
     if (fileWriter!=null) { 
      try { 
       fileWriter.close(); 
      } catch (IOException e) {     
      } 
     } 
    } 
} 

private void validateNotNull(String name,Object obj) { 
    if (obj==null) { 
     throw new NullPointerException(name+" is null."); 
    }   
}  
private void validate(Path directory) throws IOException {   
    File file = directory.toFile(); 
    if (!file.exists()) { 
     throw new IOException("Directory ["+file.getAbsolutePath()+"] do not exists."); 
    } else if (!file.isDirectory()) { 
     throw new IOException("Directory ["+file.getAbsolutePath()+"] is not a directory."); 
    } else if (!file.canRead()) {    
     throw new IOException("Can not read from directory ["+file.getAbsolutePath()+"]."); 
    } else if (!file.canWrite()) { 
     throw new IOException("Can not write to directory ["+file.getAbsolutePath()+"] ."); 
    }  
} 

private void log(String msg) { 
    //TODO 
    System.out.println("Task ["+getName()+"] "+msg); 
} 
} 
0
package p1; 

import java.io.File; 
import java.io.IOException; 
import java.nio.file.Files; 
import java.nio.file.Path; 
import java.nio.file.Paths; 
import static java.nio.file.LinkOption.NOFOLLOW_LINKS; 
import java.nio.file.StandardWatchEventKinds; 
import java.nio.file.WatchEvent; 
import java.nio.file.WatchKey; 
import java.nio.file.WatchService; 
import java.util.List; 

public class WatchForFile { 

    public void WatchMyFolder(String path) 
    { 
     File dir = new File(path); 
     Path myDir= dir.toPath(); 
      try 
      { 
       Boolean isFolder = (Boolean) Files.getAttribute(myDir,"basic:isDirectory", NOFOLLOW_LINKS); 
       if (!isFolder) 
       { 
        throw new IllegalArgumentException("Path: " + myDir + " is not a folder"); 
       } 
      } 
      catch (IOException ioe) 
      { 
       ioe.printStackTrace(); 
      } 

      System.out.println("Watching path: " + myDir); 

     try { 
      WatchService watcher = myDir.getFileSystem().newWatchService(); 
      myDir.register(watcher, StandardWatchEventKinds.ENTRY_CREATE,StandardWatchEventKinds.ENTRY_DELETE, StandardWatchEventKinds.ENTRY_MODIFY); 

      WatchKey watckKey = watcher.take(); 

      List<WatchEvent<?>> events = watckKey.pollEvents(); 

      for (WatchEvent event : events) { 
       if (event.kind() == StandardWatchEventKinds.ENTRY_CREATE) { 
        System.out.println("Created: " + event.kind().toString()); 

       } 
       if (event.kind() == StandardWatchEventKinds.ENTRY_DELETE) { 
        System.out.println("Delete: " + event.context().toString()); 
       } 
       if (event.kind() == StandardWatchEventKinds.ENTRY_MODIFY) { 
        System.out.println("Modify: " + event.context().toString()); 
       } 
      } 

     } 
     catch (Exception e) 
     { 
      System.out.println("Error: " + e.toString()); 
     } 
    } 
}