7

我有以下代码用于监视文件夹以了解 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
        }
}

只要文件的修改(在我的情况下主要是添加)是 1 对 1 完成的,并且每次添加时都会有一点延迟,这整个事情就可以完美地工作。但是,如果我拖放或同时添加多个文件。此代码仅检测第一个文件的事件,而不检测其余文件。我什至将执行时间以纳秒为单位,但没有帮助。我想知道整个代码是一种正确的方法。有人能帮我吗。谢谢。

4

2 回答 2

1

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..

于 2012-08-22T17:37:02.810 回答
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);
}
于 2019-06-13T09:30:53.970 回答