尝试对从Delete directories recursively in Java采取的递归删除方法中的偶然java.nio.file.DirectoryNotEmptyException进行故障排除
代码(贷方为@TrevorRobinson):

static void removeRecursive(Path path) throws IOException {
    Files.walkFileTree(path, new SimpleFileVisitor<Path>() {

        final Logger logger = LoggerFactory.getLogger(this.getClass());
        @Override
        public FileVisitResult visitFile(Path file,
                BasicFileAttributes attrs) throws IOException {
            logger.warn("Deleting " + file.getFileName());
            Files.delete(file);
            logger.warn("DELETED " + file.getFileName());
            return FileVisitResult.CONTINUE;
        }

        @Override
        public FileVisitResult visitFileFailed(Path file, IOException exc) {
            // try to delete the file anyway, even if its attributes could
            // not be read, since delete-only access is theoretically possible
            // I NEVER SEE THIS
            logger.warn("Delete file " + file + " failed", exc);
            try {
                Files.delete(file);
            } catch (IOException e) {
                logger.warn(
                    "Delete file " + file + " failed again", exc);
            }
            return FileVisitResult.CONTINUE;
        }

        @Override
        public FileVisitResult postVisitDirectory(Path dir, IOException exc)
                throws IOException {
            if (exc == null) {
                Files.delete(dir);
                return FileVisitResult.CONTINUE;
            }
            // directory iteration failed; propagate exception
            throw exc;
        }
    });
}

呼叫:
try {
    removeRecursive(Paths.get(unzipDirPath));
} catch (IOException e) {
    String msg = "Failed to delete folder " + unzipDirPath;
    if (e instanceof java.nio.file.DirectoryNotEmptyException) {
        msg += ". Still contains : ";
        final File[] listFiles = Paths.get(unzipDirPath).toFile().listFiles();
        if (listFiles != null) for (File file : listFiles) {
            msg += file.getAbsolutePath() + "\n";
        }
    }
    log.error(msg, e);
}

打印(一次20/40次迭代):
22:03:34.190 [http-bio-8080-exec-47] WARN  g.u.d.m.server.servlets.Controller$1 - Deleting batt
22:03:34.192 [http-bio-8080-exec-47] WARN  g.u.d.m.server.servlets.Controller$1 - DELETED batt
22:03:34.192 [http-bio-8080-exec-47] WARN  g.u.d.m.server.servlets.Controller$1 - Deleting wifi
22:03:34.193 [http-bio-8080-exec-47] WARN  g.u.d.m.server.servlets.Controller$1 - DELETED wifi
22:03:34.196 [http-bio-8080-exec-47] ERROR g.u.d.m.s.s.DataCollectionServlet - Failed to delete folder C:\yada\. Still contains : C:\yada\dir\wifi

java.nio.file.DirectoryNotEmptyException: C:\yada\dir
    at sun.nio.fs.WindowsFileSystemProvider.implDelete(WindowsFileSystemProvider.java:265) ~[na:1.7.0_45]
    at sun.nio.fs.AbstractFileSystemProvider.delete(AbstractFileSystemProvider.java:103) ~[na:1.7.0_45]
    at java.nio.file.Files.delete(Files.java:1077) ~[na:1.7.0_45]
    at gr.uoa.di.monitoring.server.servlets.Controller$1.postVisitDirectory(Controller.java:128) ~[Controller$1.class:na]
    at gr.uoa.di.monitoring.server.servlets.Controller$1.postVisitDirectory(Controller.java:1) ~[Controller$1.class:na]
    at java.nio.file.FileTreeWalker.walk(FileTreeWalker.java:224) ~[na:1.7.0_45]
    at java.nio.file.FileTreeWalker.walk(FileTreeWalker.java:199) ~[na:1.7.0_45]
    at java.nio.file.FileTreeWalker.walk(FileTreeWalker.java:69) ~[na:1.7.0_45]
    at java.nio.file.Files.walkFileTree(Files.java:2600) ~[na:1.7.0_45]
    at java.nio.file.Files.walkFileTree(Files.java:2633) ~[na:1.7.0_45]
    at gr.uoa.di.monitoring.server.servlets.Controller.removeRecursive(Controller.java:96) ~[Controller.class:na]
    at gr.uoa.di.monitoring.server.servlets.DataCollectionServlet.doPost(DataCollectionServlet.java:153) ~[DataCollectionServlet.class:na]
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:641) [servlet-api.jar:na]
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:722) [servlet-api.jar:na]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:305) [catalina.jar:7.0.32]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210) [catalina.jar:7.0.32]
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:222) [catalina.jar:7.0.32]
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:123) [catalina.jar:7.0.32]
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:472) [catalina.jar:7.0.32]
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:168) [catalina.jar:7.0.32]
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:99) [catalina.jar:7.0.32]
    at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:929) [catalina.jar:7.0.32]
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118) [catalina.jar:7.0.32]
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:407) [catalina.jar:7.0.32]
    at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1002) [tomcat-coyote.jar:7.0.32]
    at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:585) [tomcat-coyote.jar:7.0.32]
    at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:310) [tomcat-coyote.jar:7.0.32]
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145) [na:1.7.0_45]
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615) [na:1.7.0_45]
    at java.lang.Thread.run(Thread.java:744) [na:1.7.0_45]

请注意,wifi被报告为已删除-更奇怪的是,有时我会得到:

无法删除文件夹C:\ yada。仍包含:C:\ yada \ dir
java.nio.file.DirectoryNotEmptyException:C:\ yada \ dir

我倾向于得出这样的结论,即删除有时会花费太长时间-换句话说,问题是java.nio.file.Files.delete(Path path)不会阻塞(因此C:\ yada \ dir在其时间到了时仍包含文件,有时在我删除该文件时统计它)。那么我该如何解决呢?
另外:java.nio.file.Files.delete(Path path)是否需要抛出? docs状态:

在某些操作系统上,当此Java虚拟机或其他程序打开并使用文件时,可能无法删除该文件。

在这种情况下,似乎不需要引发异常。是否需要java.nio.file.Files.delete(Path path)抛出?

最佳答案

我遇到了同样的问题,原来是由于我要从中删除内容的同一目录的代码中未关闭目录文件流而导致的。返回的流对象:

Files.list(Path)


必须关闭,因此如果使用该方法,请确保在代码中使用try-with-resources构造。

因此,我认为删除的时间不会太长,我尝试了一次尝试,然后重新尝试删除目录,但没有任何运气。您自己的程序很可能已锁定该资源。结果是,尽管它成功返回,但对它的delete调用并未完成(看起来Windows最终将在您自己的程序释放该文件后删除该文件),但是当然不能删除包含目录,因为该目录确实尚未删除空的。

08-06 05:23
查看更多