我一直在编写一个程序来监视目录,当在其中创建文件时,它会更改名称并将它们移动到新目录。在我的第一个实现中,我使用了 Java 的 Watch Service API,当我测试 1kb 文件时,它运行良好。出现的问题是,实际上创建的文件大小在 50-300mb 之间。当这种情况发生时,观察者 API 会立即找到该文件,但无法移动它,因为它仍在写入中。我尝试将观察者放入循环中(这会生成异常,直到可以移动文件为止),但这似乎效率很低。
由于这不起作用,我尝试使用计时器每 10 秒检查一次文件夹,然后在可能的情况下移动文件。这就是我最终采用的方法。
问题:当文件写入完成时是否有任何信号发出信号而不进行异常检查或不断比较大小?我喜欢对每个文件仅使用一次 Watcher API 的想法,而不是不断地检查计时器(并遇到异常)。
非常感谢所有回复!
nt
我今天遇到了同样的问题。在我的用例中,在文件实际导入之前的一个小延迟并不是一个大问题,而且我仍然想使用 NIO2 API。我选择的解决方案是等到文件10秒没有被修改后再对其执行任何操作。
实现的重要部分如下。程序将一直等待,直到等待时间到期或发生新事件。每次修改文件时都会重置过期时间。如果在等待时间到期之前删除文件,则会将其从列表中删除。我使用 poll 方法,超时时间为预期的过期时间,即 (lastmodified+waitTime)-currentTime
private final Map<Path, Long> expirationTimes = newHashMap();
private Long newFileWait = 10000L;
public void run() {
for(;;) {
//Retrieves and removes next watch key, waiting if none are present.
WatchKey k = watchService.take();
for(;;) {
long currentTime = new DateTime().getMillis();
if(k!=null)
handleWatchEvents(k);
handleExpiredWaitTimes(currentTime);
// If there are no files left stop polling and block on .take()
if(expirationTimes.isEmpty())
break;
long minExpiration = min(expirationTimes.values());
long timeout = minExpiration-currentTime;
logger.debug("timeout: "+timeout);
k = watchService.poll(timeout, TimeUnit.MILLISECONDS);
}
}
}
private void handleExpiredWaitTimes(Long currentTime) {
// Start import for files for which the expirationtime has passed
for(Entry<Path, Long> entry : expirationTimes.entrySet()) {
if(entry.getValue()<=currentTime) {
logger.debug("expired "+entry);
// do something with the file
expirationTimes.remove(entry.getKey());
}
}
}
private void handleWatchEvents(WatchKey k) {
List<WatchEvent<?>> events = k.pollEvents();
for (WatchEvent<?> event : events) {
handleWatchEvent(event, keys.get(k));
}
// reset watch key to allow the key to be reported again by the watch service
k.reset();
}
private void handleWatchEvent(WatchEvent<?> event, Path dir) throws IOException {
Kind<?> kind = event.kind();
WatchEvent<Path> ev = cast(event);
Path name = ev.context();
Path child = dir.resolve(name);
if (kind == ENTRY_MODIFY || kind == ENTRY_CREATE) {
// Update modified time
FileTime lastModified = Attributes.readBasicFileAttributes(child, NOFOLLOW_LINKS).lastModifiedTime();
expirationTimes.put(name, lastModified.toMillis()+newFileWait);
}
if (kind == ENTRY_DELETE) {
expirationTimes.remove(child);
}
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)