Попытка устранить случайный java.nio.file.DirectoryNotEmptyException
в рекурсивном методе удаления, взятом из рекурсивно удалять каталоги в Java
Код (кредит для @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)
бросить?