gpt4 book ai didi

java - Files.delete 和 Files.deleteIfExists 的行为有点奇怪

转载 作者:行者123 更新时间:2023-12-02 07:18:06 24 4
gpt4 key购买 nike

我得到这样的代码:

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); }
});

在调用删除方法后,我的空目录被锁定(在调用后立即检查它),但直到应用程序关闭后才被删除。我觉得有点奇怪,但想知道为什么会发生这种情况。

(我使用 Windows 10)

最佳答案

来自 Files.list(Path) 的文档:

This method must be used within a try-with-resources statement or similar control structure to ensure that the stream's open directory is closed promptly after the stream's operations have completed.

您没有这样做,所以 Files.deleteIfExists(…) 的以下部分适用:

On some operating systems it may not be possible to remove a file when it is open and in use by this Java virtual machine or other programs.

你应该使用

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 调用。

更简洁的解决方案是记住移动何时失败。当没有移动失败时,仍然不为空的目录应被视为错误情况,应像任何其他错误一样报告,例如

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); }
});

关于java - Files.delete 和 Files.deleteIfExists 的行为有点奇怪,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48311252/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com