我有以下代码用于监视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
}
}
只要文件的修改(在我的情况下主要是添加)是逐个完成的,并且在每次添加中有一个小延迟,这整个过程都很完美。但是,如果我拖放,或同时添加几个文件。此代码仅检测第一个文件的事件,而不检测其余文件。我甚至把执行时间都用在纳秒内,但它没有帮助。我想知道这整个代码是这样做的当前方式。有人能帮我吗。感谢。
答案 0 :(得分:1)
为什么不在每个文件夹(metadata
)中存储recursively
个文件,在metadata
个文件中,您可以存储file list
和modified 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);
}