该篇主要完成如何获取本地资源信息。
1.设计目的
- 发送方:要发送资源,需要先获取本地资源信息。 信息包括,资源编号,资源相对路径,资源信息。
- 接收方,需要将接收到的资源存储到本地与接收方相应的位置。
2.主要功能
- 生成本地资源信息列表
- 创建资源目录
- 检查本地缺失资源
3.0 文件目录遍历
文件目录是树形结构,遍历整个文件,采用队列按层次遍历。
/**
* <p>树 队列层次遍历法 处理目录下文件,生成FileInfo</p>
* <p>生成每一个文件目录路径集合</p>
* @param root 资源绝对根 为了获取资源相对路径
* @param cur 当前文件夹
* @param hander 处理方法 针对文件夹与文件
*/
private void scannDirectory(String root,File cur,IFileHander hander) {
int fileIndex = 0;
LinkedList<File> queue = new LinkedList<>();
queue.add(cur);
while (!queue.isEmpty()) {
//获取队头目录
File file = queue.removeFirst();
File[] files = file.listFiles();
if (files == null) {
continue;
}
//遍历该目录下所有文件
for (File fi : files) {
//处理文件
if (fi.isFile()) {
hander.dealResourceFile(root,fi, fileIndex++);
} else if (fi.isDirectory()){
//处理目录
hander.dealDirectory(fi, root);
//将子目录加入队尾
queue.addLast(fi);
}
}
}
}
3.1检查资源路径
检查文件路径是否正确并生成文件对象。
/**
* 本地资源绝对路径,组合给定的资源的相对路径,定位文件
* @param resourceRoot 资源相对根
* @return 生成文件
* @throws Exception 无效资源路径
*/
public File locatingFile(String resourceRoot) throws Exception {
if (this.absoluteRoot == null) {
throw new Exception("请先设置资源相对根");
}
File root = new File(absoluteRoot + resourceRoot);
if (!root.exists()) {
throw new Exception("资源根[" + resourceRoot + "]不存在");
}
return root;
}
3.2 发送端扫描本地资源
- 生成文件相对路径
- 获取文件信息
/**
* 再相对给定路径下,处理所有文件和目录
* 记录文件位置 用于接收端文件路径的创建
* 记录文件信息(文件编号,路径,长度) 为以后提供文件分割列表做数据基础
* @param resourceRoot 资源根相对路径
* @throws Exception 无效路径
*/
public void scanResourceRoot(String resourceRoot) throws Exception {
if (resourceRoot.startsWith("//")) {
resourceRoot = resourceRoot.replace("//", "");
}
this.resourceRoot = resourceRoot;
scannDirectory(absoluteRoot, locatingFile(resourceRoot),new IFileHander() {
//存储文件相对路径
@Override
public void dealDirectory(File file, String root) {
directoryList.add(file.getAbsolutePath().substring(root.length()));
}
//获取文件信息
@Override
public void dealResourceFile(String root, File file, int fileIndex) {
int index = root.length();
String path = file.getAbsolutePath().substring(index);
FileInfo fileInfo = new FileInfo(path, file.getName(), file.length());
fileList.put(fileInfo.getId(), fileInfo);
}
});
}
3.3接收端检查本地缺失资源
/**
* 检测本地资源的完成性,若有缺失,则生成资源缺失列表
* @return List<FileInfo> 资源缺失列表
* @throws Exception 文件路径异常
*/
public Collection<FileInfo> checkLocalResource() throws Exception {
//拷贝接收端资源信息
Map<Long, FileInfo> resources = new HashMap<>();
for (Map.Entry<Long, FileInfo> entry : fileList.entrySet()) {
resources.put(entry.getKey(),entry.getValue());
}
scannDirectory(this.absoluteRoot, locatingFile(resourceRoot), new IFileHander() {
Map<Long, FileInfo> resources;
public IFileHander setRequestFileList( Map<Long, FileInfo> requestFileList) {
this.resources = requestFileList;
return this;
}
@Override
public void dealDirectory(File file, String root) {
}
//删除本地已存在资源
@Override
public void dealResourceFile(String root, File file, int fileIndex) {
int id = ( file.getAbsolutePath().replace(root,"") + file.getName()).hashCode();
resources.remove(id);
}
}.setRequestFileList(resources));
//返回缺失资源
return resources.values();
}
4.接收端创建资源路径
接收端根据发送端的资源相对路径,设置本地资源绝对根后,创建资源路径。
@SuppressWarnings("ResultOfMethodCallIgnored")
public void createDirctories(String absoluteRoot) {
if (!absoluteRoot.endsWith("\\")) {
absoluteRoot += "\\";
}
this.absoluteRoot = absoluteRoot;
File file = new File(this.absoluteRoot);
if (!file.exists()) {
file.mkdirs();
}
for (String dirPath : this.directoryList) {
File curDir = new File(this.absoluteRoot + dirPath);
if (!curDir.exists()) {
curDir.mkdirs();
}
}
}
5.整体代码
package man.kuke.core;
import java.io.File;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
/**
* 该类用于描述资源信息
* 信息包括 资源编号,资源定位,资源组成
*/
public class ResourceInfo {
/**
* 资源编号
*/
private int id;
/**
* 本地资源绝对根路径
*/
private String absoluteRoot;
/**
* 文件信息列表
*/
private Map<Long,FileInfo> fileList;
/**
* 文件目录相对路径
* 用于接收端文件路径的创建
*/
private List<String> directoryList;
private String resourceRoot;
public ResourceInfo() {
/**
* 保证插入有序性
*/
this.fileList = new LinkedHashMap<>();
directoryList = new LinkedList<>();
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getFilePathById(long fileId) {
FileInfo fileInfo = fileList.get(fileId);;
return fileInfo==null? null :fileInfo.getPath();
}
public String getAbsoluteRoot() {
return absoluteRoot;
}
/**
* 用于设定绝对根,并检测有效性
* @param absoluteRoot 绝对根路径
* @throws Exception 资源路径不存在!
*/
public void setAbsoluteRoot(String absoluteRoot) throws Exception {
if (!absoluteRoot.endsWith("\\")) {
absoluteRoot += "\\";
}
this.absoluteRoot = absoluteRoot;
File file = new File(absoluteRoot);
if (!file.exists()) {
throw new Exception("资源路径不存在!");
}
}
public void addFile(FileInfo fileInfo) {
fileList.put(fileInfo.getId(), fileInfo);
}
public Collection<FileInfo> getFiles() {
return fileList.values();
}
/**
* 检测本地资源的完成性,若有缺失,则生成资源缺失列表
* @return List<FileInfo> 资源缺失列表
* @throws Exception 文件路径异常
*/
public Collection<FileInfo> checkLocalResource() throws Exception {
//拷贝接收端资源信息
Map<Long, FileInfo> resources = new HashMap<>();
for (Map.Entry<Long, FileInfo> entry : fileList.entrySet()) {
resources.put(entry.getKey(),entry.getValue());
}
scannDirectory(this.absoluteRoot, locatingFile(resourceRoot), new IFileHander() {
Map<Long, FileInfo> resources;
public IFileHander setRequestFileList( Map<Long, FileInfo> requestFileList) {
this.resources = requestFileList;
return this;
}
@Override
public void dealDirectory(File file, String root) {
}
//删除本地已存在资源
@Override
public void dealResourceFile(String root, File file, int fileIndex) {
int id = ( file.getAbsolutePath().replace(root,"") + file.getName()).hashCode();
resources.remove(id);
}
}.setRequestFileList(resources));
//返回缺失资源
return resources.values();
}
/**
* 本地资源绝对路径,组合给定的资源的相对路径,定位文件
* @param resourceRoot 资源相对根
* @return 生成文件
* @throws Exception 无效资源路径
*/
public File locatingFile(String resourceRoot) throws Exception {
if (this.absoluteRoot == null) {
throw new Exception("请先设置绝对根");
}
File root = new File(absoluteRoot + resourceRoot);
if (!root.exists()) {
throw new Exception("资源根[" + resourceRoot + "]不存在");
}
return root;
}
/**
* 再相对给定路径下,处理所有文件和目录
* 记录文件位置 用于接收端文件路径的创建
* 记录文件信息(文件编号,路径,长度) 为以后提供文件分割列表做数据基础
* @param resourceRoot 资源根相对路径
* @throws Exception 无效路径
*/
public void scanResourceRoot(String resourceRoot) throws Exception {
if (resourceRoot.startsWith("//")) {
resourceRoot = resourceRoot.replace("//", "");
}
this.resourceRoot = resourceRoot;
scannDirectory(absoluteRoot, locatingFile(resourceRoot),new IFileHander() {
//存储文件相对路径
@Override
public void dealDirectory(File file, String root) {
directoryList.add(file.getAbsolutePath().substring(root.length()));
}
//获取文件信息
@Override
public void dealResourceFile(String root, File file, int fileIndex) {
int index = root.length();
String path = file.getAbsolutePath().substring(index);
FileInfo fileInfo = new FileInfo(path, file.getName(), file.length());
fileList.put(fileInfo.getId(), fileInfo);
}
});
}
/**
* 创建绝对根资源目录
* @param absoluteRoot
*/
@SuppressWarnings("ResultOfMethodCallIgnored")
public void createDirctories(String absoluteRoot) {
if (!absoluteRoot.endsWith("\\")) {
absoluteRoot += "\\";
}
this.absoluteRoot = absoluteRoot;
File file = new File(this.absoluteRoot);
if (!file.exists()) {
file.mkdirs();
}
for (String dirPath : this.directoryList) {
File curDir = new File(this.absoluteRoot + dirPath);
if (!curDir.exists()) {
curDir.mkdirs();
}
}
}
/**
* <p>树队列层次遍历法 处理目录下文件,生成FileInfo</p>
* <p>生成每一个文件目录路径集合</p>
* @param root 资源绝对根
* @param cur 当前文件夹
* @param hander 处理接口方法
*/
private void scannDirectory(String root,File cur,IFileHander hander) {
int fileIndex = 0;
LinkedList<File> queue = new LinkedList<>();
queue.add(cur);
while (!queue.isEmpty()) {
//获取队头目录
File file = queue.removeFirst();
File[] files = file.listFiles();
if (files == null) {
continue;
}
//遍历该目录下所有文件
for (File fi : files) {
//处理文件
if (fi.isFile()) {
hander.dealResourceFile(root,fi, fileIndex++);
} else if (fi.isDirectory()){
//处理目录
hander.dealDirectory(fi, root);
//将子目录加入队尾
queue.addLast(fi);
}
}
}
}
//文件资源信息访问器
public Iterator<FileInfo> fileInfoAccessor() {
return new ArrayList<>(fileList.values()).iterator();
}
}