我得到了这样的代码:
paths.forEach(folderPath -> {
Path to = folderPath.getRoot().resolve(folderPath.getParent().subpath(0, folderPath.getNameCount() - 1)); // До имени (исключительно)
try {
Files.list(folderPath).forEach(filePath -> {
try { Files.move(filePath, to.resolve(filePath.getFileName()), StandardCopyOption.ATOMIC_MOVE); }
catch (IOException e) { processException(e); }
});
if (Files.list(folderPath).count() == 0)
Files.deleteIfExists(folderPath); // this call
} catch (IOException e) { processException(e); }
});
在我调用delete方法之后,我将我的空目录锁定(在调用它之后,检查它),但在应用程序关闭之前不会删除。我觉得有点奇怪,但想知道为什么会这样。
(我使用的是Windows 10)
答案 0 :(得分:0)
来自Files.list(Path)
的文档:
必须在try-with-resources语句或类似的控制结构中使用此方法,以确保在流的操作完成后立即关闭流的打开目录。
您没有这样做,因此Files.deleteIfExists(…)的以下部分适用:
在某些操作系统上,当该文件在此Java虚拟机或其他程序中打开并正在使用时,可能无法删除该文件。
你应该使用
paths.forEach(folderPath -> {
Path to = folderPath.getParent();
try {
try(Stream<Path> files = Files.list(folderPath)) {
files.forEach(filePath -> {
try{Files.move(filePath, to.resolve(filePath.getFileName()), ATOMIC_MOVE);}
catch (IOException e) { processException(e); }
});
}
try {
Files.deleteIfExists(folderPath);
} catch(DirectoryNotEmptyException ex) {
// may happen as you continue when Files.move fails,
// but you already reported the original exception then
}
} catch (IOException e) { processException(e); }
});
这会在尝试删除目录之前关闭文件流。请注意,第二个流操作已被删除,这种预检是浪费的,并且在所有move
操作成功时都应该不需要。但如果某些其他应用程序同时插入新文件,则无法保证在Files.list(folderPath).count() == 0
检查和后续deleteIfExists
调用之间不会发生这种情况。
更清洁的解决方案是记住move
失败的时间。如果没有move
失败,则应将仍然不为空的目录视为错误情况,应该像任何其他错误一样进行报告,例如
paths.forEach(folderPath -> {
Path to = folderPath.getParent();
try {
boolean allMovesSucceeded;
try(Stream<Path> files = Files.list(folderPath)) {
allMovesSucceeded = files
.map(filePath -> {
try {
Files.move(filePath, to.resolve(filePath.getFileName()), ATOMIC_MOVE);
return true;
}
catch(IOException e) { processException(e); return false; }
}).reduce(Boolean.TRUE, Boolean::logicalAnd);
}
if(allMovesSucceeded) Files.deleteIfExists(folderPath);
} catch (IOException e) { processException(e); }
});