Java 删除文件夹后的AccessDeniedException
我运行测试用例并将执行期间创建的文件保存在“execution”目录中(每个测试中的文件保存在单独的子目录中) 在套件开始时,我要清理此文件夹 因此,在@BeforeSuite方法中,我读取了“execution”目录中的所有项:Java 删除文件夹后的AccessDeniedException,java,file,exception,delete-file,access-denied,Java,File,Exception,Delete File,Access Denied,我运行测试用例并将执行期间创建的文件保存在“execution”目录中(每个测试中的文件保存在单独的子目录中) 在套件开始时,我要清理此文件夹 因此,在@BeforeSuite方法中,我读取了“execution”目录中的所有项: public static List<File> getRecursivelyAllFilesFromDirectory(String directory) throws IOException { List<File> files =
public static List<File> getRecursivelyAllFilesFromDirectory(String directory) throws IOException {
List<File> files = new ArrayList<>();
files.addAll(readAllFilesFromDirectory(directory));
List<File> subDirs = readSubdirectories(directory);
subDirs.forEach(dir -> {
try {
files.addAll(readAllFilesFromDirectory(dir.getPath()));
files.add(dir);
} catch (IOException e) {
e.printStackTrace();
}
});
return files;
}
我收到一个例外:
java.nio.file.AccessDeniedException: D:\...\src\test\resources\execution\TC01
at sun.nio.fs.WindowsException.translateToIOException(WindowsException.java:83)
at sun.nio.fs.WindowsException.rethrowAsIOException(WindowsException.java:97)
at sun.nio.fs.WindowsException.rethrowAsIOException(WindowsException.java:102)
at sun.nio.fs.WindowsFileSystemProvider.createDirectory(WindowsFileSystemProvider.java:504)
at java.nio.file.Files.createDirectory(Files.java:674)
at utils.ExecutionUtils.setTestCaseDir(ExecutionUtils.java:56)
at integration.steps.StepDefs.beforeScenario(StepDefs.java:29)
尽管setTestCaseDir方法中的ReadSubdirections()返回空列表,但仍会发生这种情况。
我在文件资源管理器中看到这些子目录是可见的,但我也无法访问它们。
由于此异常导致执行失败时,此子文件夹将被解锁并消失
什么进程可能会锁定此子文件夹以及如何解决此问题?请注意,对层次结构中的文件执行任何未关闭的长期操作都会阻止删除工作-因此,请检查在这些目录上运行的其他测试,并为目录流添加try-with资源(
文件
列表/newDirectoryStream)和文件
输入/输出流(在Windows上也是MappedByteBuffer
)
修复后,带有文件的文件访问者
。walkFileTree
提供了一种更可靠的删除树的方法,并且比递归的文件更快。在大型目录树上列出
:
public static void main(String[] args) throws IOException {
var paths = Arrays.stream(args).map(Path::of).collect(Collectors.toList());
FileVisitor<Path> deleteTree = new FileVisitor<>() {
public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException {
return FileVisitResult.CONTINUE;
}
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
System.out.println("Delete FILE "+file);
Files.delete(file);
return FileVisitResult.CONTINUE;
}
public FileVisitResult visitFileFailed(Path file, IOException exc) throws IOException {
throw exc;
}
public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException {
System.out.println("Delete DIR "+dir);
Files.delete(dir);
return FileVisitResult.CONTINUE;
}
};
for (Path p : paths) {
Files.walkFileTree(p, deleteTree);
}
}
publicstaticvoidmain(字符串[]args)引发IOException{
var Path=Arrays.stream(args).map(Path::of).collect(Collectors.toList());
FileVisitor deleteTree=新FileVisitor(){
公共文件VisitResult preVisitDirectory(路径目录,基本文件属性属性属性)引发IOException{
返回FileVisitResult.CONTINUE;
}
公共文件VisitResult visitFile(路径文件,基本文件属性属性属性)引发IOException{
System.out.println(“删除文件”+文件);
文件。删除(文件);
返回FileVisitResult.CONTINUE;
}
公共文件VisitResult visitFileFailed(路径文件,IOException exc)引发IOException{
抛出exc;
}
公共文件VisitResult postVisitDirectory(路径目录,IOException exc)引发IOException{
System.out.println(“删除目录”+DIR);
删除(dir);
返回FileVisitResult.CONTINUE;
}
};
用于(路径p:路径){
walkFileTree(p,deleteTree);
}
}
受@DuncG的启发,我使用NIO2和Java8解决了这个问题
public static void cleanExecutionDirectory() throws IOException {
LOGGER.info("Cleaning execution directory...");
File executionDir = new File(getExecutionDir());
if (executionDir.exists()) {
Path executionDirPath = Paths.get(getExecutionDir());
Files.walk(executionDirPath)
.sorted(Comparator.reverseOrder())
.forEach(path -> {
try {
Files.delete(path);
} catch (IOException e) {
e.printStackTrace();
}
});
LOGGER.info(String.format("Items deleted"));
}
executionDir.mkdir();
}
您不显示
readSubdirectories
,这是否使用目录流?这是完整的堆栈跟踪吗?这里少了很多。显示出错时的getExecutionDir()
,readSubdirectories()
,readAllFilesFromDirectory()
和相关变量的值。readSubdirs()
是否返回文件深度优先还是宽度优先?如果没有看到我之前评论中列出的方法,我们可能无法帮助您。
public static void main(String[] args) throws IOException {
var paths = Arrays.stream(args).map(Path::of).collect(Collectors.toList());
FileVisitor<Path> deleteTree = new FileVisitor<>() {
public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException {
return FileVisitResult.CONTINUE;
}
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
System.out.println("Delete FILE "+file);
Files.delete(file);
return FileVisitResult.CONTINUE;
}
public FileVisitResult visitFileFailed(Path file, IOException exc) throws IOException {
throw exc;
}
public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException {
System.out.println("Delete DIR "+dir);
Files.delete(dir);
return FileVisitResult.CONTINUE;
}
};
for (Path p : paths) {
Files.walkFileTree(p, deleteTree);
}
}
public static void cleanExecutionDirectory() throws IOException {
LOGGER.info("Cleaning execution directory...");
File executionDir = new File(getExecutionDir());
if (executionDir.exists()) {
Path executionDirPath = Paths.get(getExecutionDir());
Files.walk(executionDirPath)
.sorted(Comparator.reverseOrder())
.forEach(path -> {
try {
Files.delete(path);
} catch (IOException e) {
e.printStackTrace();
}
});
LOGGER.info(String.format("Items deleted"));
}
executionDir.mkdir();
}