简体   繁体   中英

How to monitor a folder for changes in java?

I have the below code for monitoring a folder for any changes in java:

    public class FolderWatcher
    {
    // public List<Event> events = new ArrayList<Event>();

    public static Event call() throws IOException, InterruptedException
    {
        LOG.info("Watching folder");
        Path _directotyToWatch = Paths.get("data/input-files"); // this will be put in the configuration file
        WatchService watcherSvc = FileSystems.getDefault().newWatchService();
        WatchKey watchKey = _directotyToWatch.register(watcherSvc,  ENTRY_CREATE, ENTRY_DELETE, ENTRY_MODIFY);

        watchKey = watcherSvc.take();
        for (WatchEvent<?> event : watchKey.pollEvents())
        {
            WatchEvent<Path> watchEvent = castEvent(event);
            LOG.info(event.kind().name().toString() + " " + _directotyToWatch.resolve(watchEvent.context()));
            String eventName = event.kind().name();
            String fileName = _directotyToWatch.resolve(watchEvent.context()).toString();
            watchKey.reset();
            return new Event(eventName, fileName);
        }
        return null;

    }

@SuppressWarnings("unchecked")
static <T> WatchEvent<T> castEvent(WatchEvent<?> event)
{
    return (WatchEvent<T>) event;
}

}

and:

public abstract class AbstractWatcher
{
    abstract void eventDetected(Event event);

    private final ScheduledExecutorService threadpool;

    public AbstractWatcher(ScheduledExecutorService threadpool)
    {
        this.threadpool = threadpool;
    }

    public AbstractWatcher()
    {
        threadpool = Executors.newSingleThreadScheduledExecutor();
    }


    public void handle()
    {
        final FolderWatcherHandler handler = new FolderWatcherHandler();

        final Runnable r = new Runnable()
        {
            @Override
            public void run()
            {
                try
                {
                    Event event = FolderWatcher.call();
                    if (event != null)
                    {
                        handler.eventDetected(event);
                    }
                }
                catch (IOException e)
                {
                        LOG.error("failed to watch the update", e);
                 }
                catch (InterruptedException e)
                {
                    LOG.info("thread interrupted", e);
                    Thread.currentThread().interrupt();
                    return;
                }

            }
        };

        Runtime.getRuntime().addShutdownHook(new Thread()
        {
            @Override
            public void run()
            {
                    threadpool.shutdown();

            }
        });

        threadpool.scheduleWithFixedDelay(r, 0, 1, TimeUnit.NANOSECONDS);
    }
}

and:

public class FolderWatcherHandler extends AbstractWatcher
{
    @Override
    public void eventDetected(Event event)
    {
         // Do stuff
        }
}

This whole thing works perfect as long as modifications of files(in my case mostly adding) is done 1 by 1 with a small delay within each addition. However, if I drag and drop, or add several files at the same time. This code only detects the event for the first file and not the rest. I even put the excecution time in Nanoseconds but it didn't help. I am wondering of this whole code is a currect way of doing this. Can someone help me. thanks.

Why don't you store a metadata file in each folder ( recursively ), in that metadata file you can store file list and modified date and size of each file. Your thread should compare this metadata file in each folder with the current files present in the same. That is how you can detect any change within that folder.

Remember you should do it recursively for each subfolder within that. And the metadata file should be updated with each scan. Hope this helps..

in my case, this code was successfull:

try {
    Path rootFolder = Paths.get(ctxProperties.getProperty("rootFolder"));
    WatchService watcher = rootFolder.getFileSystem().newWatchService();
    rootFolder.register(watcher, StandardWatchEventKinds.ENTRY_CREATE);
    while (true) {
        WatchKey watchKey = watcher.take();
        if (watchKey != null) {
            for (WatchEvent event : watchKey.pollEvents()) {
                if (StandardWatchEventKinds.ENTRY_CREATE.equals(event.kind())) {
                    String fileName = rootFolder.toString() + "/" + event.context().toString();
                    String messageStr = convertFileToString(fileName);
                    if (messageStr != null) {
                        try {
                            sendMessage(jmsPublisher, messageStr, getJmsProperties());
                            moveMessageToProcessedDirectory(fileName, ctxProperties.getProperty("successFolder"), ".ok");
                            LOGGER.info("JMS message successfully sent");
    sleep(Long.parseLong(ctxProperties.getProperty("sleepBetweenMsgMse")));
                        } catch (Exception e) {
                            moveMessageToProcessedDirectory(fileName, ctxProperties.getProperty("errorFolder"), ".nok");
                        }
                    } else {
                        LOGGER.error("ERROR: error parsing file content to string with file: " + fileName);
                        moveMessageToProcessedDirectory(fileName, ctxProperties.getProperty("errorFolder"), ".nok");
                    }
                }
            }
            boolean valid = watchKey.reset();
            if (!valid) {
                LOGGER.error("ERROR: the watcher is no longer valid, the directory is inaccessible");
                break;
            }
        } else {
            LOGGER.error("ERROR: the watcher is null or not watchable");
            break;
        }
    }
} catch (InterruptedException interruptedException) {
    LOGGER.error("InterruptedException: thread got interrupted",interruptedException);
} catch (Exception exception) {
    LOGGER.error("Exception: " + exception.getMessage(), exception);
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM