Beobachten eines Verzeichnisses für Änderungen in Java

Lesezeit: 12 Minuten

Ich möchte ein Verzeichnis auf Dateiänderungen überwachen. Und ich habe WatchService in java.nio verwendet. Ich kann erfolgreich auf das Ereignis „Datei erstellt“ lauschen. Aber ich kann nicht auf Dateiänderungsereignisse lauschen. Ich überprüfte Offizielles Java-Tutorialaber immer noch kämpfen.

Hier ist der Quellcode.

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());
    }
    }

  • Welches Betriebssystem und welche Version von Java?

    – Verrückter Programmierer

    4. Mai 2014 um 4:28 Uhr

  • Windows 8 und Java 1.7

    – Isuru

    4. Mai 2014 um 4:43 Uhr

  • Hast du die “Aktie” probiert? WatchDir.java ? Es funktioniert zumindest unter Linux.

    – Benutzer3159253

    4. Mai 2014 um 5:44 Uhr

Benutzer-Avatar
vvg

Tatsächlich haben Sie fälschlicherweise Veranstaltungen abonniert. Nur der letzte Listener wurde mit dem Ereignistyp ENTRY_DELETE registriert.

Um sich für alle Arten von Veranstaltungen gleichzeitig anzumelden, sollten Sie Folgendes verwenden:

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

Benutzer-Avatar
Hindol

Warnung! Schamlose Eigenwerbung!

Ich habe einen Wrapper um Java 1.7 erstellt WatchService das ermöglicht die Registrierung eines Verzeichnisses und einer beliebigen Anzahl von Kugel Muster. Diese Klasse kümmert sich um die Filterung und gibt nur Ereignisse aus, an denen Sie interessiert sind.

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();

Vollständiger Code ist darin Repo.

  • Stimmen Sie für die Komplettlösung ab. Eine kleine Empfehlung jedoch, beachten Sie, dass das Beispiel nur auf Java 8 funktioniert. Verstehen Sie mich nicht falsch, ich LIEBE Lambdas, aber Java 7 ist heutzutage viel verbreiteter, also musste ich es auf Java 7 umrüsten, als ich es benutzte. Ich werde bald die “fixed” Version für diejenigen veröffentlichen, die Java 8 noch nicht verwenden können

    – Nicolas Terry

    11. Oktober 2015 um 20:02 Uhr

  • Hey, danke für die Mühe. Das Unternehmen, für das ich arbeite, hat bereits auf Java 8 umgestellt, da der Java 7-Supportzyklus beendet ist. Aus diesem Grund hatte ich keinen zwingenden Grund, Java 7 zu unterstützen. Ich werde den Gist-Titel aktualisieren, um dies widerzuspiegeln.

    – Hindol

    12. Oktober 2015 um 7:07 Uhr

  • Ich habe gerade das Gist-Zip heruntergeladen und es mit Java 1.7 versucht. Es kann nicht finden import java.util.stream und einige default Methoden. @nterry Hast du die Java 7-Version irgendwo veröffentlicht? Danke.

    – elysch

    4. November 2015 um 16:18 Uhr

  • Ich habe ein Problem damit, dass ich eine Datei in das Verzeichnis herunterlade, aber ich brauche sie, um die Aktion auszuführen, NACHDEM der Download abgeschlossen ist. Gibt es eine Möglichkeit, das zu tun?

    – duliha

    15. März 2016 um 23:04 Uhr

  • @thouliha Ich habe hier einen guten Ansatz gefunden – stackoverflow.com/a/1391218/1019491. Versuchen Sie grundsätzlich, die Datei umzubenennen, und wenn Sie erfolgreich sind, ist der Download abgeschlossen. Ich hoffe, dass der Browser die Datei sperrt, während sie heruntergeladen wird.

    – Hindol

    21. März 2016 um 4:45 Uhr

Ich habe einige Kurse dafür gemacht.

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

und

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;
}
}

und

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;
}
}

und

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);
}
}

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());
        }
    }
}

Benutzer-Avatar
Omkar Marathe

Überprüfen Sie diesen Code …

https://github.com/omkar9999/FileWatcherHandler

Dieses Projekt ermöglicht das Überwachen von Dateien auf verschiedene Dateiereignisse wie Erstellen, Ändern und Löschen und das anschließende Handeln auf diese Ereignisse auf generische Weise.

Wie benutzt man?

Erstellen Sie ein Path-Objekt, das das Verzeichnis darstellt, das auf Dateiereignisse überwacht werden soll.

Path path = Paths.get("/home/omkar/test");

Implementieren Sie die FileHandler-Schnittstelle, um eine Aktion auszuführen, die durch ein registriertes Dateiereignis erkannt wird.

public class FileHandlerTest implements FileHandler {

    private static final Logger LOGGER = Logger.getLogger(FileHandlerTest.class.getName());

    /*
     * This implemented method will delete the file
     * 
     * @see com.io.util.FileHandler#handle(java.io.File,
     * java.nio.file.WatchEvent.Kind)
     */
    public void handle(File file, Kind<?> fileEvent) {
        LOGGER.log(Level.INFO,"Handler is triggered for file {0}",file.getPath());
        if(fileEvent == StandardWatchEventKinds.ENTRY_CREATE) {
            try {
                boolean deleted = Files.deleteIfExists(Paths.get(file.getPath()));
                assertTrue(deleted);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

}

Erstellen Sie eine Instanz eines implementierten FileHandler

FileHandlerTest fileHandlerTest = new FileHandlerTest();

Erstellen Sie eine Instanz eines FileWatcher, indem Sie den Pfad, eine Instanz eines implementierten FileHandlers und Typen von Dateiereignissen, die Sie überwachen möchten, durch Kommas getrennt übergeben.

FileWatcher fileWatcher = new FileWatcher(path, fileHandlerTest, StandardWatchEventKinds.ENTRY_CREATE);

Jetzt einen neuen Thread erstellen und starten.

Thread watcherThread = new Thread(fileWatcher);
watcherThread.start();

Dieser Thread beginnt mit der Abfrage Ihrer registrierten Dateiereignisse und ruft Ihre benutzerdefinierte Handle-Methode auf, sobald eines der registrierten Ereignisse erkannt wird.

Benutzer-Avatar
Dikla

public class FileWatcher implements Runnable {

private static final Logger LOGGER =Logger.getLogger(FileWatcher.class.getName());

private WatchService watcher;
private FileHandler fileHandler;
private List<Kind<?>> watchedEvents;
private Path directoryWatched;

/**
 * @param directory
 * @Path directory to watch files into
 * @param fileHandler
 * @FileHandler implemented instance to handle the file event
 * @param watchRecursive
 *            if directory is to be watched recursively
 * @param watchedEvents
 *            Set of file events watched
 * 
 * @throws IOException
 */
public FileWatcher(Path directory, FileHandler fileHandler, boolean watchRecursive,
        WatchEvent.Kind<?>... watchedEvents) throws IOException {
    super();
    this.watcher = FileSystems.getDefault().newWatchService();
    this.fileHandler = fileHandler;
    this.directoryWatched = directory;
    this.watchedEvents = Arrays.asList(watchedEvents);
    if (watchRecursive) {
        // register all subfolders
        Files.walkFileTree(directory, new SimpleFileVisitor<Path>() {
            @Override
            public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException {
                LOGGER.log(Level.INFO, "Registering {0} ", dir);
                dir.register(watcher, StandardWatchEventKinds.ENTRY_CREATE, StandardWatchEventKinds.ENTRY_DELETE,
                        StandardWatchEventKinds.ENTRY_MODIFY);
                return FileVisitResult.CONTINUE;
            }
        });
    } else {
        directory.register(watcher, watchedEvents);
    }
}

@SuppressWarnings({ "unchecked" })
public void run() {
    LOGGER.log(Level.INFO, "Starting FileWatcher for {0}", directoryWatched.toAbsolutePath());
    WatchKey key = null;
    while (true) {
        try {
            key = watcher.take();
            if (key != null) {
                for (WatchEvent<?> event : key.pollEvents()) {
                    WatchEvent.Kind<?> kind = event.kind();

                    WatchEvent<Path> ev = (WatchEvent<Path>) event;
                    //directory in which file event is detected
                    Path directory = (Path) key.watchable(); 
                    Path fileName = ev.context();
                    if (watchedEvents.contains(kind)) {
                        LOGGER.log(Level.INFO, "Invoking handle on {0}", fileName.toAbsolutePath());
                        fileHandler.handle(directory.resolve(fileName).toFile(), kind);
                    }
                }
                key.reset();
            }
        } catch (InterruptedException ex) {
            LOGGER.log(Level.SEVERE, "Polling Thread was interrupted ", ex);
            Thread.currentThread().interrupt();
        }
    }
}

}

1014370cookie-checkBeobachten eines Verzeichnisses für Änderungen in Java

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy