我之前使用的方法,还以为自己好醒呢,想到了类似与文件的广度遍历,然后将文件删除
/**
* 删除不是服务目录下的文件夹
* @param path 存储项目的根目录
* @param serviceFileList 指定后缀文件的父目录的列表
*/
public static void deleteNotServiceFile(String path, List serviceFileList) {
Path serivceRootPath = Paths.get(path);
Queue<Path> queue = new LinkedList<>();
boolean offer = queue.offer(serivceRootPath);
if (offer) {
Queue<Path> paths1 = bfsFileTree(queue, serviceFileList);
deleteNullDir(paths1,serivceRootPath);
}
}
public static Queue<Path> bfsFileTree(Queue<Path> treePath, List hasPropertiesFile) {
Queue<Path> queue = new LinkedList<>();
while (!treePath.isEmpty()) {
//遍历子目录
Path root = treePath.poll();
try (DirectoryStream<Path> stream = Files.newDirectoryStream(root)) {
for (Path p : stream) {
//是否是文件夹
if (Files.isDirectory(p, LinkOption.NOFOLLOW_LINKS)) {
boolean contains = hasPropertiesFile.contains(p);
//是否是服务文件夹
if (!contains) {
treePath.offer(p);
}
continue;
}
//删除文件
Files.deleteIfExists(p);
//加入到文件夹中
}
//删除上一层的空文件
File file = new File(root.toString());
File[] listFiles = file.listFiles();
if (listFiles.length <= 0) {
//文件夹无有文件
queue.offer(root);
}else {
Files.deleteIfExists(root);
}
} catch (IOException e) {
}
}
return queue;
}
/**
* 删除空文件夹的路径
* @param paths
* @param start
*/
public static void deleteNullDir(Queue<Path> paths,Path start) {
while (!paths.isEmpty()) {
//等于最原始目录就不能删除
Path poll = paths.poll();
if (poll.toString().equals(start.toString())){
continue;
}
try {
Files.deleteIfExists(poll);
} catch (IOException e) {
//e.printStackTrace();
}
if (poll.getParent() != null) {
paths.offer(poll.getParent());
}
}
}
无语,参考了之前写移动文件到父目录的方法:java:父目录中的只有一个文件夹(子目录),将子目录的内容移动到父目录中_VC卷心菜的博客-CSDN博客我重新写了一个类去实现这样的功能。
import java.io.File;
import java.io.IOException;
import java.nio.file.FileVisitResult;
import java.nio.file.FileVisitor;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.List;
public class ServiceFileVisitorOperation implements FileVisitor<Path> {
/**
* 存储指定后缀文件的父目录
*/
private List<Path> servicePaths;
public ServiceFileVisitorOperation( List<Path> servicePaths){
this.servicePaths=servicePaths;
}
@Override
public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException {
if (servicePaths!=null){
if (servicePaths.contains(dir)){
return FileVisitResult.SKIP_SUBTREE;
}
}
return FileVisitResult.CONTINUE;
}
@Override
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
System.out.println("删除文件:"+file.toString());
if (!servicePaths.contains(file.getParent())){
Files.deleteIfExists(file);//删除文件
}
return FileVisitResult.CONTINUE;
}
@Override
public FileVisitResult visitFileFailed(Path file, IOException exc) throws IOException {
System.out.println("操作失败");
return FileVisitResult.TERMINATE;
}
@Override
public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException {
int file = new File(dir.toString()).list().length;
if (file==0){
System.out.println("删除文件夹:"+dir.toString());
Files.deleteIfExists(dir);
}
return FileVisitResult.CONTINUE;
}
}
遍历行为控制器FileVisitor
接口java.nio.file.FileVisitor包含四个方法,涉及到遍历过程中的几个重要的步骤节点。一般实际中使用SimpleFileVisitor简化操作。
preVisitDirectory 访问一个目录,在进入之前调用。
postVisitDirectory 一个目录的所有节点都被访问后调用。遍历时跳过同级目录或有错误发生,Exception会传递给这个方法
visitFile 文件被访问时被调用。该文件的文件属性被传递给这个方法
visitFileFailed 当文件不能被访问时,此方法被调用。Exception被传递给这个方法
public enum FileVisitResult {
CONTINUE,
TERMINATE,
SKIP_SUBTREE,
SKIP_SIBLINGS;
}
- CONTINUE: 继续遍历
- SKIP_SIBLINGS: 继续遍历,但忽略当前目录的所有兄弟节点直接返回上一层继续遍历
- SKIP_SUBTREE: 当
preVisitDirectory
返回此值时,将跳过指定的目录及其子目录。这个树枝是“修剪出来”的树。 - TERMINATE 终止遍历