该方法首先获取所有的文件和文件夹,然后根据父子关系遍历生成树形结构的文件列表。
一、相关方法介绍
1.ArrayListMultimap
官方文档描述如下:
This multimap allows duplicate key-value pairs. After adding a new key-value pair equal to an existing key-value pair, the {@code ArrayListMultimap} will contain entries for both the new value and the old value.
此多映射允许重复的键值对。添加与现有键值对相等的新键值对后,{@code ArrayListMultimap}将包含新值和旧值的条目。
也就是说,ArrayListMultimap是一个key到多个value的映射关系的数据结构,本质上还是Map。其常用方法如下:
//创建一键多值的ArrayListMultimap集合
ArrayListMultimap<String, String> mutimap = ArrayListMultimap.create();
//get方法和put方法
List<String> strings = mutimap.get("key");
fileMutimap.put("key", "value");
//keys方法和keySet方法
Multiset<String> keys = mutimap.keys();
Set<String> strings = fileMutimap.keySet();
//size方法
int size = fileMutimap.size();
2.Files.walkFileTree
为了方便直接使用该方法遍历文件,当然也可选择使用其他方法读取文件。
walkFileTree()包含用于递归遍历目录树的方法,方法参数接收一个Path对象和一个FileVisitor对象,Path对象指向需要遍历的目录FileVisitor在遍历的时候调用。FileVisitor接口定义了四个方法,调用时间如下:
- preVisitDirectory():在访问任意目录前调用;
- postVisitDirectory():在访问任意目录完成后调用;
- visitFile():在访问到每个文件时调用;
- visitFileFaild():在访问文件失败是调用
二、实例
为了方便,直接使用FileVO类和Controller类来展示代码逻辑。
1.FileVo类
根据目录结构创建文件实体类,目录应包含目录名,父目录名,文件列表和子目录列表。
@Data
public class FileVO {
/**
* 父目录,在传递给前端时忽略此字段
*/
@JsonIgnore
private String parent;
/**
* 目录名
*/
private String directory;
/**
* 文件列表
*/
private List<String> fileName;
/**
* 子目录
*/
private List<FileVO> children;
}
2.Controller
@RestController
@RequestMapping(path = "/file")
public class FileController {
@PostMapping("/getFiles")
public List<FileVO> getFiles(String dir) throws IOException {
//确定根节点
String root = dir;
//文件列表
ArrayListMultimap<String, String> fileMutimap = ArrayListMultimap.create();
//目录集合
ArrayListMultimap<String, FileVO> dirMutimap = ArrayListMultimap.create();
//根目录集合
List<FileVO> ancestors = new ArrayList<>();
Files.walkFileTree(Paths.get(dir), new SimpleFileVisitor<Path>() {
//遍历文件
@Override
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) {
fileMutimap.put(file.getParent().toString(), file.getFileName().toString());
return FileVisitResult.CONTINUE;
}
//遍历目录
@Override
public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) {
FileVO fileVO = new FileVO();
String dirName = dir.toString();
fileVO.setDirectory(dirName);
fileVO.setParent(dir.getParent().toString());
//填充文件到目录
fileVO.setFileName(fileMutimap.get(dirName));
//是否为根节点
if (StringUtils.equals(dirName, root)) {
ancestors.add(fileVO);
}
dirMutimap.put(dir.getParent().toString(), fileVO);
return FileVisitResult.CONTINUE;
}
});
if (CollectionUtils.isNotEmpty(ancestors)) {
for (FileVO ancestor : ancestors) {
recursionBuild(dirMutimap, ancestor);
}
}
return ancestors;
}
public void recursionBuild(ArrayListMultimap<String, FileVO> dirMultimap, FileVO ancestor) {
List<FileVO> children = dirMultimap.get(ancestor.getDirectory());
if (CollectionUtils.isEmpty(children)) {
return;
}
ancestor.setChildren(children);
for (FileVO child : children) {
recursionBuild(dirMultimap, child);
}
}
}
三、postman测试结果
[
{
"directory": "G:\\test",
"fileName": [
"aa.txt"
],
"children": [
{
"directory": "G:\\test\\test01",
"fileName": [
"test01_aa.jpg",
"test01_bb.jpg"
],
"children": [
{
"directory": "G:\\test\\test01\\test03",
"fileName": [
"03_aa.jpg",
"03_bb.jpg"
],
"children": null
}
]
},
{
"directory": "G:\\test\\test02",
"fileName": [
"test02_aa.jpg",
"test02_bb.jpg"
],
"children": null
}
]
}
]