【发布时间】:2015-03-07 21:23:45
【问题描述】:
我目前正在尝试为我正在编写的应用程序实现更新程序。 目前流程如下:
- 从类路径(例如 app.jar)中提取 updater.jar 到系统的临时目录
- 打开一个套接字以侦听更新程序的终止请求
- 启动updater.jar
- 然后更新程序检查是否有可用的更新程序
- 如果有可用更新,更新程序会向应用发送终止请求(通过打开的套接字)
- 更新程序将新版本下载到系统临时目录
- 更新程序将所有文件从新版本复制到应用的基本目录(覆盖现有文件)
此过程中存在问题的部分是将新版本的文件副本复制到应用程序的 basedir 中,因为应用程序的基本目录中的某些文件可能由于某种原因被锁定(即用户在此目录中打开了一个文件)。
因此,可能会发生一些文件已被复制而有些文件没有被复制的情况 - 留下不一致的状态并且可能无法执行应用程序。
为了防止这种情况,我所做的是在复制新文件之前检查应用程序的 basedir 中是否有任何锁定的文件。为此,我编写了一个 util 方法:
public static boolean isLocked(File pFile){
if (pFile == null || !pFile.exists()){
return false;
}
if (!pFile.canWrite()) return true;
if (!pFile.renameTo(pFile)) return true;
try {
final FileChannel tFileChannel = FileChannel.open(pFile.toPath(), StandardOpenOption.WRITE);
final FileLock tLock = tFileChannel.tryLock();
try {
if (tLock == null){
return true;
} else {
tLock.release();
}
} finally {
tFileChannel.close();
}
} catch (final IOException | OverlappingFileLockException ex) {
return true;
}
return false;
}
但我仍然认为这个过程很容易出错,因为我不知道isLocked() 方法是否在所有情况下都能提供可靠的结果。
即使是这样,锁定状态也仅在调用方法时有效 -> 文件可能在调用后立即被锁定(例如通过防病毒扫描程序)。
所以我的问题是:有没有更可靠的方法来复制一组文件?也许在某种可回滚的文件事务中?
【问题讨论】: