如何监视文件夹中的java更改?

时间:2012-08-22 16:21:45

标签: java multithreading file file-io

我有以下代码用于监视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;
}

}

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

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

只要文件的修改(在我的情况下主要是添加)是逐个完成的,并且在每次添加中有一个小延迟,这整个过程都很完美。但是,如果我拖放,或同时添加几个文件。此代码仅检测第一个文件的事件,而不检测其余文件。我甚至把执行时间都用在纳秒内,但它没有帮助。我想知道这整个代码是这样做的当前方式。有人能帮我吗。感谢。

2 个答案:

答案 0 :(得分:1)

为什么不在每个文件夹(metadata)中存储recursively个文件,在metadata个文件中,您可以存储file listmodified date以及每个文件的size。您的主题应该将每个文件夹中的metadata文件与同一个文件夹中的current files进行比较。 这就是你如何检测该文件夹中的任何变化。

请记住,您应该为其中的每个subfolder递归执行此操作。并且每次扫描都应更新metadata文件。 希望这会有所帮助..

答案 1 :(得分:0)

在我的情况下,此代码成功:

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