简体   繁体   English

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

[英]How to monitor a folder for changes in java?

I have the below code for monitoring a folder for any changes in java: 我有以下代码用于监视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. 为什么不在每个文件夹中存储metadata文件( recursively ),在该metadata文件中,您可以存储file list以及modified date每个文件的modified datesize Your thread should compare this metadata file in each folder with the current files present in the same. 您的线程应该将每个文件夹中的此metadata文件与同一current files存在的current files进行比较。 That is how you can detect any change within that folder. 这就是您可以检测该文件夹中的任何更改的方法。

Remember you should do it recursively for each subfolder within that. 请记住,您应该为其中的每个subfolder递归执行此操作。 And the metadata file should be updated with each scan. 每次扫描都应更新metadata文件。 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);
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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