2011-11-30 111 views
3

我有一个实现了一个侦听器,通知我们是否在特定目录中接收到新文件。这是通过轮询和使用TimerTask来实现的。 现在程序已经设置好,一旦它接收到一个新文件,它就会调用另一个java程序来打开文件并验证它是否是正确的文件。我的问题是,由于轮询发生了指定的秒数,因此可能会出现文件被复制到该目录中并因此被窗口锁定的情况。如何在java中打开文件之前等待windows进程完成之前

由于尝试打开它进行验证的其他Java程序无法(“文件正被另一个进程使用”),所以会抛出IOException。

有什么办法可以知道Windows何时完成了复制,然后调用第二个程序从java中进行验证?

如果有人需要它们以帮助,我将非常乐意发布代码片段。

感谢

+0

其他的java程序有读取或写入? – havexz

回答

3

这一个有点棘手。如果你可以控制或者至少与拷贝文件的程序进行通信,那将是小菜一碟,但是我猜这对于Windows来说是不可能的。我不得不在前段时间用SFU软件处理类似的问题,我通过循环尝试打开文件进行写入直到其可用,从而解决了这个问题。

为了避免循环时CPU使用率过高,检查文件可以在an exponential distribution速率下完成。

编辑一个可能的解决方案:

File fileToCopy = File(String pathname); 
int sleepTime = 1000; // Sleep 1 second 
while(!fileToCopy .canWrite()){ 
    // Cannot write to file, windows still working on it 
    Sleep(sleepTime); 
    sleepTime *= 2; // Multiply sleep time by 2 (not really exponential but will do the trick) 
    if(sleepTime > 30000){ 
     // Set a maximum sleep time to ensure we are not sleeping forever :) 
     sleepTime = 30000; 
    } 
} 
// Here, we have access to the file, go process it 
processFile(fileToCopy); 
+0

这听起来像一个有效的选项。你可以给我一个小的示例代码,如何实现指数循环,如果它试图打开文件失败? – Eosphorus

+0

@ user1074440完成!请看我的编辑。 – GETah

+0

这个工作。非常感谢。然而,filetoCopy.canWrite()或filetoCopy.canRead()将永远是真实的,即使窗户有锁。所以我们需要尝试打开文件和捕获异常而不是while循环。再次感谢,我将标记此解决 – Eosphorus

0

我想你可以创建File对象,然后使用canReadcanWrite知道是否文件已准备好由其它Java程序中使用。

http://docs.oracle.com/javase/6/docs/api/java/io/File.html

另一种选择是试图在第一个程序打开文件,并在它抛出异常然后不调用其他Java程序。但我会推荐以上'File选项。

+2

canRead实际上并未说明该文件是否已准备好被另一个程序使用。我试图在文件正在被复制的过程中使用它,但奇怪的是,当我期待一个错误,因为该文件被窗口锁定时,该值返回true。 – Eosphorus

+0

但你应该尝试'canWrite' – havexz

+0

canWrite doesn工作要么悲伤:( – Eosphorus

4

非常感谢所有帮助,我是有WatchEvent同样的问题。 不幸的是,正如你所说的,即使文件仍然被Windows锁定,file.canRead()和file.canWrite()都返回true。所以我发现,如果我尝试用相同的名称“重命名”它,我知道Windows是否在使用它。所以这就是我所做的:

while(!sourceFile.renameTo(sourceFile)) { 
     // Cannot read from file, windows still working on it. 
     Thread.sleep(10); 
    } 
+1

这是一个很好的解决方法@jfajunior。我以类似的方式做了。我只是试图打开该文件,它会给出一个例外,因为Windows正在处理它。所以我发现异常让线程像你一样睡觉,并在上述建议的指数循环之后再次尝试。很高兴这篇文章帮助你 – Eosphorus

相关问题