2014-01-24 86 views
1

假设我有我的目录结构如下所示:删除文件,只有当所有的可删除 - 饶无辜

mydirectory中
>文件1
>文件2
>文件3
> UndeletableFile
> FILE4

假设我已经实现了一个递归算法来删除一个文件夹的内容,然后是文件夹本身和/或使用了一个极好的建议here

现在这里是我无法找到一个解决方案后,在网络上搜索一下和SO:
我想要删除整个文件夹,但我想要做到这一点只有当它会成功为每个文件和那里的子文件夹。当前的实现(确切地说为java.io.File.delete())将在被调用时立即删除文件,然后转到下一个文件。如果在删除文件夹的过程中中途遇到问题,则会在系统上留下UndeletableFileFile5以及MyDirectory

这种情况下是否有一种方法或最佳实践算法?
目标是让让可删除文件生效如果操作中途失败。毕竟他们不应该死,如果他们的家能够存活下去,对吧?

我曾经想过到目前为止:
也许这将是明智的只是重命名的所有文件,而不是先删除它们,像这样

mydirectory中
> File1temp
> File2temp
> ..

之后,如果进程失败,我可以遍历目录再次重新命名所有文件恢复正常,如果成功,我可以删除它们。

但是这对我来说效率非常低,是不是有更好的解决方案? 在我看来,这应该是一个共同的问题,请提供一个链接,如果我忽略了一些东西

+0

除您的应用程序之外,还有哪些人可以使用此文件?谁制造他们?其他过程?它由您或其第三方软件管理? – Mikhail

+0

@Mikhail用户可能会直接影响该文件夹。它们由另一个应用程序生成。当时没有其他进程正在运行。由我管理。 **但是我想强调一下:**没关系,如果它现在失败了,我只想回到“不要删除任何东西”,如果发生什么事情 – avalancha

回答

2

没有完全安全的方法来做到这一点。

最好的办法是扫描所有文件,检查是否允许删除它们。只有扫描成功了,你才能进行实际的删除操作。

问题在于,如果扫描后某些内容被锁定,但在删除之前删除仍会在该文件上失败。

唯一的选择是保留所有文件的副本(即将它们移动到回收站,将它们存储在一个zip文件中等),直到所有的删除成功为止,然后清空bin /删除zip文件 - 如果不恢复。

但即使如此,还是有可能阻止恢复。

真的,你会在这里遇到边缘案例,你需要做的是确定它们是什么,并决定在每种情况下期望的行为。

+0

你能详细说明如何最好地检查我是否'm'被允许删除“please? – avalancha

+0

这应该有所帮助:http://docs.oracle.com/javase/7/docs/api/java/io/File.html#canWrite%28%29 –

+0

我认为复制它们/将它们移动到一个zip是均匀的更多的工作比重命名的想法,但除此之外,一个很好的答案,谢谢 – avalancha

0

您可以先使用一种非破坏性的方法来检查是否有任何文件可以被删除,例如,在UNIX上检查文件本身及其包含的目录是否可写。然后递归地计算哪些目录可以被删除,然后在第二遍中删除那些驻留在被计算为可删除的目录内的文件和目录。这种方法的问题是,在操作正在进行时,别人可能会修改目录或文件内容或权限,因此您仍然可能得到错误的结果。

重命名不是一个傻瓜式的解决方案,要么是因为如果一个程序有文件或目录的句柄,它可以在对象重命名时保留该句柄。因此,即使您重命名文件或将其移至“安全”位置,如果文件存在打开的句柄,其他人也可以更改其权限。

没有一种适用于所有平台的傻瓜式方法,因为底层文件系统可以被其他进程同时操作。

对于单用户场景,使用第一段概述的双通道方法应该可行。

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的骆驼集成框架,必须看看它的File组件。唯一的问题是第二个过程也应遵循相同的协议,否则它不会有任何影响。

+0

这是一个好主意!但是,我是否正确地理解,我仍然必须将这与蒂姆的答案结合起来?因为这不会检查文件当前是否可供我锁定在第一位,对吗? – avalancha

+0

如果用户不手动访问文件,并且所有操作都通过基于信号量的协议完成,则不必重命名文件。一旦获得信号量,您可以安全地删除文件。这很像Java中的同步块。 – Mikhail

+1

是的,信号量文件运行良好 - 但只有在_everything_访问这些文件时才使用信号量文件。即使一个进程/用户忽略该文件也会破坏它。 –