【发布时间】:2016-03-24 22:39:26
【问题描述】:
有一些与此类似的 Java 问题,但没有一个接受我能找到的答案,而且我的情况更具体一些。我有一个程序,在将文件输入目录时一次处理一个文件。有时,这些文件可能会在我的程序可见后被程序删除几秒钟后仍处于锁定状态。我无法控制那个程序。在我的程序中,当我的程序尝试读取文件时,如果文件正在使用中,我已经有错误处理来恢复它。它会导致文件被完全跳过。我想要实现的是一个重试方案,以查看文件是否在几秒钟后解锁。在另一个问题中,我发现了使用FileUtils.touch() 的建议。这很方便,因为我已经在我的项目中使用了 FileUtils。根据 javadoc,FileUtils.touch() 如果文件正被另一个进程使用,则抛出 IOException。听起来很棒。但是,我提到的答案中的一个 cmets 在没有任何解释的情况下警告了比赛条件。这是我正在考虑实施的代码:
// Implementing Sason's suggestion
int retries = 0;
while (retries < MAX_RETRIES) {
try {
processFile(file);
} catch (IOException ioe) {
// Assumes this is a file in use exception... bad thing?
log.warn("File is in use. Waiting 1 second to retry.");
retries++;
try {
Thread.sleep(1000);
} catch (InterruptedException ie) {
log.warn("Thread interrupted while waiting for file lock to clear.");
break;
}
}
}
我意识到文件可能在 FileUtils.touch() 和 processFile() 方法调用之间再次被锁定(我认为这是在我找到的未接受答案中警告的竞争条件),但这很好。 processFile() 方法将像当前一样处理锁定错误。需要明确的是,在这种情况下,文件被另一个进程打开但不能被锁定是完全可以的。
此外,虽然有时文件确实会在一两秒后解锁,但在某些情况下,删除文件的程序会无限期地保持锁定。我还需要避免无限地尝试重新处理同一个文件,并且能够在重试用尽后无法处理文件时通知发件人。
那么我在这里遗漏了什么吗?有没有更好/更安全的方法来做到这一点?
【问题讨论】:
-
这听起来不像
touch()是测试文件是否打开的可靠方法。它可能在具有特定进程的特定系统上运行,这很好,但是如果您在其他地方运行代码或更改编写器,则需要重新测试以确保它仍然有效。正确的做法是使用FileLock,但这需要编写程序使用底层文件系统锁定机制。 -
我的问题应该更清楚。如果文件在另一个没有锁定文件的进程中打开(例如,NotePad++),则可以。它只是无法锁定,因为
processFile()将尝试锁定文件。我确实明白你关于FileLock的观点,但你说得对,它需要进行相当多的重构。我确实认为touch()可以跨平台工作,但需要注意的是另一个程序可能会打开文件但未锁定。