假设我有以下目录结构:
mydirectory中
> File1中
> file2的
> File3
> UndeletableFile
> FILE4
假设我已经实现了一个递归算法来删除文件夹的内容,然后删除文件夹本身和/或使用了一个很好的建议here
现在这里是我在网上搜索SO之后无法找到解决方案的问题:我想要删除整个文件夹,但我想这样做如果它将成功存在于那里的每个文件和子文件夹。当前的实现(准确地称为java.io.File.delete()
)将在调用文件后立即删除文件,然后转到下一个文件。如果删除文件夹失败,如上例所示,系统上会留下UndeletableFile
和File5
以及MyDirectory
。
对于这种情况,是否有常规方法或最佳实践算法?
如果操作 中途失败,目标是让可删除文件生效。毕竟他们不应该死,如果他们的家能够存活,对吗?
到目前为止我的想法是什么:
也许首先重命名所有文件而不是删除它们是明智的,就像这样
mydirectory中
> File1temp
> File2temp
> ...
之后如果进程失败,我可以再次遍历目录并重新将所有文件重命名为正常,如果成功,我可以删除它们。
但这对我来说非常低效,是不是有更好的解决方案? 在我看来,这应该是一个常见的问题,如果我忽略了某些内容,请提供链接
答案 0 :(得分:2)
没有完全安全的方法来做到这一点。
您最好的选择是扫描所有文件,检查是否允许删除它们。只有扫描成功,您才能完成并进行实际删除。
问题是,如果扫描后某些内容被锁定,但在删除之前,该文件的删除仍然会失败。
唯一的选择是保留所有文件的副本(即将它们移动到回收站,将它们存储在拉链中等),直到所有删除都成功,然后只清空bin /删除zip文件 - 如果不恢复。
但即便如此,仍有可能阻止恢复。
你真的会遇到边缘情况,你需要做的是确定它们是什么,并确定每种情况下所需的行为。
答案 1 :(得分:1)
对于您的情况,当您必须独占处理多个文件时,通常的做法是拥有一个单独的信号量文件,并在开始对文件束进行任何操作之前将其锁定。一个非常原始的例子如下:
private static RandomAccessFile raf;
public static void main(String[] args) throws IOException {
lock();
//do smth...
release();
}
private static boolean lock() throws IOException {
File f = new File("Semaphore.lck");
raf = new RandomAccessFile(f, "rw");
FileLock fl = raf.getChannel().tryLock();
return fl != null;
}
private static void release() throws IOException {
raf.close();
}
在Apache Camel集成框架中采用了类似的方法,看看它的File组件。唯一的问题是第二个过程也应遵循相同的协议,否则不会产生任何影响。
答案 2 :(得分:0)
您可以先使用非破坏性方法检查是否可以删除任何文件,例如在UNIX上检查文件本身及其包含的目录是否可写。然后递归计算可以删除哪些目录,然后在第二遍中删除那些驻留在计算为可删除的目录内的文件和目录。这种方法的问题在于其他人可能会在操作过程中修改目录或文件内容或权限,因此您仍然可能会得到错误的结果。
重命名不是一个万无一失的解决方案,因为如果程序具有文件或目录的句柄,它可以在重命名对象时保留该句柄。因此,即使您重命名文件或将其移至“安全”文件中也是如此。位置,如果有文件的打开句柄,其他人可以更改其权限。
在所有情况下都没有可用于所有平台的防呆方法,因为底层文件系统可以同时由其他进程操纵。
对于单个用户场景,使用第一段中概述的两遍方法应该有效。