【Java项目】多文件传输:本地资源获取

该篇主要完成如何获取本地资源信息。

1.设计目的

  1. 发送方:要发送资源,需要先获取本地资源信息。 信息包括,资源编号,资源相对路径,资源信息。
  2. 接收方,需要将接收到的资源存储到本地与接收方相应的位置。

2.主要功能

  1. 生成本地资源信息列表
  2. 创建资源目录
  3. 检查本地缺失资源

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 发送端扫描本地资源
  1. 生成文件相对路径
  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();
    }
    
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值