我正在使用lastModified
长值作为更改的指示,以特定间隔使用轮询在java(1.6)中编写目录监视实用程序。我发现当我的轮询间隔很小(秒)并且复制的文件很大时,在实际完成文件复制之前就会触发change事件。
我想知道是否有办法可以找到文件的状态,如传输,完成等。
环境:Java 1.6;期望在Windows和Linux上工作。
答案 0 :(得分:7)
我过去使用过两种与平台无关的方法。
1 /这是用于FTP传输的,我控制了所放置的内容,因此它可能不直接相关。
基本上,放置文件file.txt
的任何内容,当它完成时,也会放置一个名为file.txt.marker
的小(可能是零字节)虚拟文件(例如)。
这样,监视工具只查找要显示的标记文件,当它出现时,它知道真实文件已完成。然后它可以处理真实文件并删除标记。
2 /持续时间不变。
让您的监控程序等待,直到文件保持不变N秒(其中N被合理地保证足够大,文件将完成)。
例如,如果文件大小在60秒内没有改变,那么很有可能它已经完成。
在不考虑文件完成之间有一个平衡的行为,因为它没有活动,等待一旦完成就可以开始处理它。对于本地复制而言,这不是FTP的问题。
答案 1 :(得分:5)
这个解决方案对我有用:
File ff = new File(fileStr);
if(ff.exists()) {
for(int timeout = 100; timeout>0; timeout--) {
RandomAccessFile ran = null;
try {
ran = new RandomAccessFile(ff, "rw");
break; // no errors, done waiting
} catch (Exception ex) {
System.out.println("timeout: " + timeout + ": " + ex.getMessage());
} finally {
if(ran != null) try {
ran.close();
} catch (IOException ex) {
//do nothing
}
ran = null;
}
try {
Thread.sleep(100); // wait a bit then try again
} catch (InterruptedException ex) {
//do nothing
}
}
System.out.println("File lockable: " + fileStr +
(ff.exists()?" exists":" deleted during process"));
} else {
System.out.println("File does not exist: " + fileStr);
}
此解决方案依赖于以下事实:如果另一个进程打开文件,则无法打开文件进行写入。它将保持循环,直到达到超时值或文件可以打开。需要根据应用程序的实际需要调整超时值。我也尝试过使用channels和tryLock()的方法,但似乎没有必要。
答案 2 :(得分:4)
你的意思是说你正在等待lastModified
时间来解决?充其量只会有点昙花一现。
如何尝试使用写访问权限打开文件(当然是附加而不是截断文件)?如果另一个进程仍在尝试写入它,那将不会成功。它有点难看,特别是因为它可能是流控制使用异常(ick)的情况,但我认为它会起作用。
答案 3 :(得分:1)
如果我正确理解了这个问题,那么您正在寻找一种方法来区分文件的复制是完整的还是仍在进行中?
如何比较源文件和目标文件的大小(即file.length())?如果它们相等,那么复制就完成了。否则,它仍在进行中。
我不确定它是否有效,因为它仍然需要轮询。但它“可能”有效。
答案 4 :(得分:1)
您可以使用进度条技术查看在线文件上传 - 它们使用OutputStream Listener和自定义编写器来通知侦听器有关写入的字节。
http://www.missiondata.com/blog/java/28/file-upload-progress-with-ajax-and-java-and-prototype/
答案 5 :(得分:1)
我们曾经监控文件大小更改,以确定文件是否已完成。
我们使用Spring集成文件端点每200毫秒对目录进行一次轮询。
一旦检测到文件(无论是否完整),我们都有一个客户文件过滤器,它将有一个接口方法" accept(文件文件)"返回一个标志,指示我们是否可以处理该文件。
如果过滤器返回False,则将忽略此FILE实例,并在下次轮询期间为同一过滤过程提取该实例。
过滤器执行以下操作:
首先,我们获取其当前文件大小。我们将等待200毫秒(可以更少)并再次检查大小。如果大小不同,我们将重试5次。只有当文件大小停止增长时,文件才会被标记为COMPLETED。(即返回true)。
使用的示例代码如下:
public class InCompleteFileFilter<F> extends AbstractFileListFilter<F> {
protected Object monitor = new Object();
@Override
protected boolean accept(F file) {
synchronized (monitor){
File currentFile = (File)file;
if(!currentFile.getName().contains("Conv1")){return false;}
long currentSize = currentFile.length();
try { Thread.sleep(200); } catch (InterruptedException e) { e.printStackTrace(); }
int retryCount = 0;
while(retryCount++ < 4 && currentFile.length() > currentSize){
try { Thread.sleep(200); } catch (InterruptedException e) { e.printStackTrace(); }
}
if(retryCount == 5){
return false;
}else{
return true;
}
}
}
}